summaryrefslogtreecommitdiffstats
path: root/kernel/trace/blktrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/blktrace.c')
-rw-r--r--kernel/trace/blktrace.c90
1 files changed, 70 insertions, 20 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 45a3928544ce..206e0e2ace53 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -66,7 +66,8 @@ static struct tracer_flags blk_tracer_flags = {
66}; 66};
67 67
68/* Global reference count of probes */ 68/* Global reference count of probes */
69static atomic_t blk_probes_ref = ATOMIC_INIT(0); 69static DEFINE_MUTEX(blk_probe_mutex);
70static int blk_probes_ref;
70 71
71static void blk_register_tracepoints(void); 72static void blk_register_tracepoints(void);
72static void blk_unregister_tracepoints(void); 73static void blk_unregister_tracepoints(void);
@@ -329,14 +330,29 @@ static void blk_trace_free(struct blk_trace *bt)
329 kfree(bt); 330 kfree(bt);
330} 331}
331 332
333static void get_probe_ref(void)
334{
335 mutex_lock(&blk_probe_mutex);
336 if (++blk_probes_ref == 1)
337 blk_register_tracepoints();
338 mutex_unlock(&blk_probe_mutex);
339}
340
341static void put_probe_ref(void)
342{
343 mutex_lock(&blk_probe_mutex);
344 if (!--blk_probes_ref)
345 blk_unregister_tracepoints();
346 mutex_unlock(&blk_probe_mutex);
347}
348
332static void blk_trace_cleanup(struct blk_trace *bt) 349static void blk_trace_cleanup(struct blk_trace *bt)
333{ 350{
334 blk_trace_free(bt); 351 blk_trace_free(bt);
335 if (atomic_dec_and_test(&blk_probes_ref)) 352 put_probe_ref();
336 blk_unregister_tracepoints();
337} 353}
338 354
339int blk_trace_remove(struct request_queue *q) 355static int __blk_trace_remove(struct request_queue *q)
340{ 356{
341 struct blk_trace *bt; 357 struct blk_trace *bt;
342 358
@@ -349,6 +365,17 @@ int blk_trace_remove(struct request_queue *q)
349 365
350 return 0; 366 return 0;
351} 367}
368
369int blk_trace_remove(struct request_queue *q)
370{
371 int ret;
372
373 mutex_lock(&q->blk_trace_mutex);
374 ret = __blk_trace_remove(q);
375 mutex_unlock(&q->blk_trace_mutex);
376
377 return ret;
378}
352EXPORT_SYMBOL_GPL(blk_trace_remove); 379EXPORT_SYMBOL_GPL(blk_trace_remove);
353 380
354static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, 381static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
@@ -538,8 +565,7 @@ static int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
538 if (cmpxchg(&q->blk_trace, NULL, bt)) 565 if (cmpxchg(&q->blk_trace, NULL, bt))
539 goto err; 566 goto err;
540 567
541 if (atomic_inc_return(&blk_probes_ref) == 1) 568 get_probe_ref();
542 blk_register_tracepoints();
543 569
544 ret = 0; 570 ret = 0;
545err: 571err:
@@ -550,9 +576,8 @@ err:
550 return ret; 576 return ret;
551} 577}
552 578
553int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, 579static int __blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
554 struct block_device *bdev, 580 struct block_device *bdev, char __user *arg)
555 char __user *arg)
556{ 581{
557 struct blk_user_trace_setup buts; 582 struct blk_user_trace_setup buts;
558 int ret; 583 int ret;
@@ -571,6 +596,19 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
571 } 596 }
572 return 0; 597 return 0;
573} 598}
599
600int blk_trace_setup(struct request_queue *q, char *name, dev_t dev,
601 struct block_device *bdev,
602 char __user *arg)
603{
604 int ret;
605
606 mutex_lock(&q->blk_trace_mutex);
607 ret = __blk_trace_setup(q, name, dev, bdev, arg);
608 mutex_unlock(&q->blk_trace_mutex);
609
610 return ret;
611}
574EXPORT_SYMBOL_GPL(blk_trace_setup); 612EXPORT_SYMBOL_GPL(blk_trace_setup);
575 613
576#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) 614#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
@@ -607,7 +645,7 @@ static int compat_blk_trace_setup(struct request_queue *q, char *name,
607} 645}
608#endif 646#endif
609 647
610int blk_trace_startstop(struct request_queue *q, int start) 648static int __blk_trace_startstop(struct request_queue *q, int start)
611{ 649{
612 int ret; 650 int ret;
613 struct blk_trace *bt = q->blk_trace; 651 struct blk_trace *bt = q->blk_trace;
@@ -646,6 +684,17 @@ int blk_trace_startstop(struct request_queue *q, int start)
646 684
647 return ret; 685 return ret;
648} 686}
687
688int blk_trace_startstop(struct request_queue *q, int start)
689{
690 int ret;
691
692 mutex_lock(&q->blk_trace_mutex);
693 ret = __blk_trace_startstop(q, start);
694 mutex_unlock(&q->blk_trace_mutex);
695
696 return ret;
697}
649EXPORT_SYMBOL_GPL(blk_trace_startstop); 698EXPORT_SYMBOL_GPL(blk_trace_startstop);
650 699
651/* 700/*
@@ -676,7 +725,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
676 switch (cmd) { 725 switch (cmd) {
677 case BLKTRACESETUP: 726 case BLKTRACESETUP:
678 bdevname(bdev, b); 727 bdevname(bdev, b);
679 ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg); 728 ret = __blk_trace_setup(q, b, bdev->bd_dev, bdev, arg);
680 break; 729 break;
681#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64) 730#if defined(CONFIG_COMPAT) && defined(CONFIG_X86_64)
682 case BLKTRACESETUP32: 731 case BLKTRACESETUP32:
@@ -687,10 +736,10 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
687 case BLKTRACESTART: 736 case BLKTRACESTART:
688 start = 1; 737 start = 1;
689 case BLKTRACESTOP: 738 case BLKTRACESTOP:
690 ret = blk_trace_startstop(q, start); 739 ret = __blk_trace_startstop(q, start);
691 break; 740 break;
692 case BLKTRACETEARDOWN: 741 case BLKTRACETEARDOWN:
693 ret = blk_trace_remove(q); 742 ret = __blk_trace_remove(q);
694 break; 743 break;
695 default: 744 default:
696 ret = -ENOTTY; 745 ret = -ENOTTY;
@@ -708,10 +757,14 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg)
708 **/ 757 **/
709void blk_trace_shutdown(struct request_queue *q) 758void blk_trace_shutdown(struct request_queue *q)
710{ 759{
760 mutex_lock(&q->blk_trace_mutex);
761
711 if (q->blk_trace) { 762 if (q->blk_trace) {
712 blk_trace_startstop(q, 0); 763 __blk_trace_startstop(q, 0);
713 blk_trace_remove(q); 764 __blk_trace_remove(q);
714 } 765 }
766
767 mutex_unlock(&q->blk_trace_mutex);
715} 768}
716 769
717#ifdef CONFIG_BLK_CGROUP 770#ifdef CONFIG_BLK_CGROUP
@@ -1558,9 +1611,7 @@ static int blk_trace_remove_queue(struct request_queue *q)
1558 if (bt == NULL) 1611 if (bt == NULL)
1559 return -EINVAL; 1612 return -EINVAL;
1560 1613
1561 if (atomic_dec_and_test(&blk_probes_ref)) 1614 put_probe_ref();
1562 blk_unregister_tracepoints();
1563
1564 blk_trace_free(bt); 1615 blk_trace_free(bt);
1565 return 0; 1616 return 0;
1566} 1617}
@@ -1591,8 +1642,7 @@ static int blk_trace_setup_queue(struct request_queue *q,
1591 if (cmpxchg(&q->blk_trace, NULL, bt)) 1642 if (cmpxchg(&q->blk_trace, NULL, bt))
1592 goto free_bt; 1643 goto free_bt;
1593 1644
1594 if (atomic_inc_return(&blk_probes_ref) == 1) 1645 get_probe_ref();
1595 blk_register_tracepoints();
1596 return 0; 1646 return 0;
1597 1647
1598free_bt: 1648free_bt: