diff options
Diffstat (limited to 'kernel/trace/blktrace.c')
-rw-r--r-- | kernel/trace/blktrace.c | 90 |
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 */ |
69 | static atomic_t blk_probes_ref = ATOMIC_INIT(0); | 69 | static DEFINE_MUTEX(blk_probe_mutex); |
70 | static int blk_probes_ref; | ||
70 | 71 | ||
71 | static void blk_register_tracepoints(void); | 72 | static void blk_register_tracepoints(void); |
72 | static void blk_unregister_tracepoints(void); | 73 | static 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 | ||
333 | static 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 | |||
341 | static 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 | |||
332 | static void blk_trace_cleanup(struct blk_trace *bt) | 349 | static 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 | ||
339 | int blk_trace_remove(struct request_queue *q) | 355 | static 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 | |||
369 | int 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 | } | ||
352 | EXPORT_SYMBOL_GPL(blk_trace_remove); | 379 | EXPORT_SYMBOL_GPL(blk_trace_remove); |
353 | 380 | ||
354 | static ssize_t blk_dropped_read(struct file *filp, char __user *buffer, | 381 | static 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; |
545 | err: | 571 | err: |
@@ -550,9 +576,8 @@ err: | |||
550 | return ret; | 576 | return ret; |
551 | } | 577 | } |
552 | 578 | ||
553 | int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | 579 | static 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 | |||
600 | int 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 | } | ||
574 | EXPORT_SYMBOL_GPL(blk_trace_setup); | 612 | EXPORT_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 | ||
610 | int blk_trace_startstop(struct request_queue *q, int start) | 648 | static 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 | |||
688 | int 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 | } | ||
649 | EXPORT_SYMBOL_GPL(blk_trace_startstop); | 698 | EXPORT_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 | **/ |
709 | void blk_trace_shutdown(struct request_queue *q) | 758 | void 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 | ||
1598 | free_bt: | 1648 | free_bt: |