diff options
| -rw-r--r-- | block/blk-iolatency.c | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c index fc714ef402a6..1893686a9c1f 100644 --- a/block/blk-iolatency.c +++ b/block/blk-iolatency.c | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #include <linux/sched/loadavg.h> | 72 | #include <linux/sched/loadavg.h> |
| 73 | #include <linux/sched/signal.h> | 73 | #include <linux/sched/signal.h> |
| 74 | #include <trace/events/block.h> | 74 | #include <trace/events/block.h> |
| 75 | #include <linux/blk-mq.h> | ||
| 75 | #include "blk-rq-qos.h" | 76 | #include "blk-rq-qos.h" |
| 76 | #include "blk-stat.h" | 77 | #include "blk-stat.h" |
| 77 | 78 | ||
| @@ -601,6 +602,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) | |||
| 601 | return; | 602 | return; |
| 602 | 603 | ||
| 603 | enabled = blk_iolatency_enabled(iolat->blkiolat); | 604 | enabled = blk_iolatency_enabled(iolat->blkiolat); |
| 605 | if (!enabled) | ||
| 606 | return; | ||
| 607 | |||
| 604 | while (blkg && blkg->parent) { | 608 | while (blkg && blkg->parent) { |
| 605 | iolat = blkg_to_lat(blkg); | 609 | iolat = blkg_to_lat(blkg); |
| 606 | if (!iolat) { | 610 | if (!iolat) { |
| @@ -610,7 +614,7 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) | |||
| 610 | rqw = &iolat->rq_wait; | 614 | rqw = &iolat->rq_wait; |
| 611 | 615 | ||
| 612 | atomic_dec(&rqw->inflight); | 616 | atomic_dec(&rqw->inflight); |
| 613 | if (!enabled || iolat->min_lat_nsec == 0) | 617 | if (iolat->min_lat_nsec == 0) |
| 614 | goto next; | 618 | goto next; |
| 615 | iolatency_record_time(iolat, &bio->bi_issue, now, | 619 | iolatency_record_time(iolat, &bio->bi_issue, now, |
| 616 | issue_as_root); | 620 | issue_as_root); |
| @@ -754,10 +758,13 @@ int blk_iolatency_init(struct request_queue *q) | |||
| 754 | return 0; | 758 | return 0; |
| 755 | } | 759 | } |
| 756 | 760 | ||
| 757 | static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | 761 | /* |
| 762 | * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise | ||
| 763 | * return 0. | ||
| 764 | */ | ||
| 765 | static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | ||
| 758 | { | 766 | { |
| 759 | struct iolatency_grp *iolat = blkg_to_lat(blkg); | 767 | struct iolatency_grp *iolat = blkg_to_lat(blkg); |
| 760 | struct blk_iolatency *blkiolat = iolat->blkiolat; | ||
| 761 | u64 oldval = iolat->min_lat_nsec; | 768 | u64 oldval = iolat->min_lat_nsec; |
| 762 | 769 | ||
| 763 | iolat->min_lat_nsec = val; | 770 | iolat->min_lat_nsec = val; |
| @@ -766,9 +773,10 @@ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | |||
| 766 | BLKIOLATENCY_MAX_WIN_SIZE); | 773 | BLKIOLATENCY_MAX_WIN_SIZE); |
| 767 | 774 | ||
| 768 | if (!oldval && val) | 775 | if (!oldval && val) |
| 769 | atomic_inc(&blkiolat->enabled); | 776 | return 1; |
| 770 | if (oldval && !val) | 777 | if (oldval && !val) |
| 771 | atomic_dec(&blkiolat->enabled); | 778 | return -1; |
| 779 | return 0; | ||
| 772 | } | 780 | } |
| 773 | 781 | ||
| 774 | static void iolatency_clear_scaling(struct blkcg_gq *blkg) | 782 | static void iolatency_clear_scaling(struct blkcg_gq *blkg) |
| @@ -800,6 +808,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
| 800 | u64 lat_val = 0; | 808 | u64 lat_val = 0; |
| 801 | u64 oldval; | 809 | u64 oldval; |
| 802 | int ret; | 810 | int ret; |
| 811 | int enable = 0; | ||
| 803 | 812 | ||
| 804 | ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx); | 813 | ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx); |
| 805 | if (ret) | 814 | if (ret) |
| @@ -834,7 +843,12 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
| 834 | blkg = ctx.blkg; | 843 | blkg = ctx.blkg; |
| 835 | oldval = iolat->min_lat_nsec; | 844 | oldval = iolat->min_lat_nsec; |
| 836 | 845 | ||
| 837 | iolatency_set_min_lat_nsec(blkg, lat_val); | 846 | enable = iolatency_set_min_lat_nsec(blkg, lat_val); |
| 847 | if (enable) { | ||
| 848 | WARN_ON_ONCE(!blk_get_queue(blkg->q)); | ||
| 849 | blkg_get(blkg); | ||
| 850 | } | ||
| 851 | |||
| 838 | if (oldval != iolat->min_lat_nsec) { | 852 | if (oldval != iolat->min_lat_nsec) { |
| 839 | iolatency_clear_scaling(blkg); | 853 | iolatency_clear_scaling(blkg); |
| 840 | } | 854 | } |
| @@ -842,6 +856,24 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
| 842 | ret = 0; | 856 | ret = 0; |
| 843 | out: | 857 | out: |
| 844 | blkg_conf_finish(&ctx); | 858 | blkg_conf_finish(&ctx); |
| 859 | if (ret == 0 && enable) { | ||
| 860 | struct iolatency_grp *tmp = blkg_to_lat(blkg); | ||
| 861 | struct blk_iolatency *blkiolat = tmp->blkiolat; | ||
| 862 | |||
| 863 | blk_mq_freeze_queue(blkg->q); | ||
| 864 | |||
| 865 | if (enable == 1) | ||
| 866 | atomic_inc(&blkiolat->enabled); | ||
| 867 | else if (enable == -1) | ||
| 868 | atomic_dec(&blkiolat->enabled); | ||
| 869 | else | ||
| 870 | WARN_ON_ONCE(1); | ||
| 871 | |||
| 872 | blk_mq_unfreeze_queue(blkg->q); | ||
| 873 | |||
| 874 | blkg_put(blkg); | ||
| 875 | blk_put_queue(blkg->q); | ||
| 876 | } | ||
| 845 | return ret ?: nbytes; | 877 | return ret ?: nbytes; |
| 846 | } | 878 | } |
| 847 | 879 | ||
| @@ -977,8 +1009,14 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd) | |||
| 977 | { | 1009 | { |
| 978 | struct iolatency_grp *iolat = pd_to_lat(pd); | 1010 | struct iolatency_grp *iolat = pd_to_lat(pd); |
| 979 | struct blkcg_gq *blkg = lat_to_blkg(iolat); | 1011 | struct blkcg_gq *blkg = lat_to_blkg(iolat); |
| 1012 | struct blk_iolatency *blkiolat = iolat->blkiolat; | ||
| 1013 | int ret; | ||
| 980 | 1014 | ||
| 981 | iolatency_set_min_lat_nsec(blkg, 0); | 1015 | ret = iolatency_set_min_lat_nsec(blkg, 0); |
| 1016 | if (ret == 1) | ||
| 1017 | atomic_inc(&blkiolat->enabled); | ||
| 1018 | if (ret == -1) | ||
| 1019 | atomic_dec(&blkiolat->enabled); | ||
| 982 | iolatency_clear_scaling(blkg); | 1020 | iolatency_clear_scaling(blkg); |
| 983 | } | 1021 | } |
| 984 | 1022 | ||
