diff options
Diffstat (limited to 'block/blk-iolatency.c')
-rw-r--r-- | block/blk-iolatency.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c index fc714ef402a6..2620baa1f699 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 | ||
@@ -591,6 +592,7 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) | |||
591 | u64 now = ktime_to_ns(ktime_get()); | 592 | u64 now = ktime_to_ns(ktime_get()); |
592 | bool issue_as_root = bio_issue_as_root_blkg(bio); | 593 | bool issue_as_root = bio_issue_as_root_blkg(bio); |
593 | bool enabled = false; | 594 | bool enabled = false; |
595 | int inflight = 0; | ||
594 | 596 | ||
595 | blkg = bio->bi_blkg; | 597 | blkg = bio->bi_blkg; |
596 | if (!blkg || !bio_flagged(bio, BIO_TRACKED)) | 598 | if (!blkg || !bio_flagged(bio, BIO_TRACKED)) |
@@ -601,6 +603,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) | |||
601 | return; | 603 | return; |
602 | 604 | ||
603 | enabled = blk_iolatency_enabled(iolat->blkiolat); | 605 | enabled = blk_iolatency_enabled(iolat->blkiolat); |
606 | if (!enabled) | ||
607 | return; | ||
608 | |||
604 | while (blkg && blkg->parent) { | 609 | while (blkg && blkg->parent) { |
605 | iolat = blkg_to_lat(blkg); | 610 | iolat = blkg_to_lat(blkg); |
606 | if (!iolat) { | 611 | if (!iolat) { |
@@ -609,8 +614,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) | |||
609 | } | 614 | } |
610 | rqw = &iolat->rq_wait; | 615 | rqw = &iolat->rq_wait; |
611 | 616 | ||
612 | atomic_dec(&rqw->inflight); | 617 | inflight = atomic_dec_return(&rqw->inflight); |
613 | if (!enabled || iolat->min_lat_nsec == 0) | 618 | WARN_ON_ONCE(inflight < 0); |
619 | if (iolat->min_lat_nsec == 0) | ||
614 | goto next; | 620 | goto next; |
615 | iolatency_record_time(iolat, &bio->bi_issue, now, | 621 | iolatency_record_time(iolat, &bio->bi_issue, now, |
616 | issue_as_root); | 622 | issue_as_root); |
@@ -754,10 +760,13 @@ int blk_iolatency_init(struct request_queue *q) | |||
754 | return 0; | 760 | return 0; |
755 | } | 761 | } |
756 | 762 | ||
757 | static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | 763 | /* |
764 | * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise | ||
765 | * return 0. | ||
766 | */ | ||
767 | static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | ||
758 | { | 768 | { |
759 | struct iolatency_grp *iolat = blkg_to_lat(blkg); | 769 | struct iolatency_grp *iolat = blkg_to_lat(blkg); |
760 | struct blk_iolatency *blkiolat = iolat->blkiolat; | ||
761 | u64 oldval = iolat->min_lat_nsec; | 770 | u64 oldval = iolat->min_lat_nsec; |
762 | 771 | ||
763 | iolat->min_lat_nsec = val; | 772 | iolat->min_lat_nsec = val; |
@@ -766,9 +775,10 @@ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val) | |||
766 | BLKIOLATENCY_MAX_WIN_SIZE); | 775 | BLKIOLATENCY_MAX_WIN_SIZE); |
767 | 776 | ||
768 | if (!oldval && val) | 777 | if (!oldval && val) |
769 | atomic_inc(&blkiolat->enabled); | 778 | return 1; |
770 | if (oldval && !val) | 779 | if (oldval && !val) |
771 | atomic_dec(&blkiolat->enabled); | 780 | return -1; |
781 | return 0; | ||
772 | } | 782 | } |
773 | 783 | ||
774 | static void iolatency_clear_scaling(struct blkcg_gq *blkg) | 784 | static void iolatency_clear_scaling(struct blkcg_gq *blkg) |
@@ -800,6 +810,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
800 | u64 lat_val = 0; | 810 | u64 lat_val = 0; |
801 | u64 oldval; | 811 | u64 oldval; |
802 | int ret; | 812 | int ret; |
813 | int enable = 0; | ||
803 | 814 | ||
804 | ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx); | 815 | ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx); |
805 | if (ret) | 816 | if (ret) |
@@ -834,7 +845,12 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
834 | blkg = ctx.blkg; | 845 | blkg = ctx.blkg; |
835 | oldval = iolat->min_lat_nsec; | 846 | oldval = iolat->min_lat_nsec; |
836 | 847 | ||
837 | iolatency_set_min_lat_nsec(blkg, lat_val); | 848 | enable = iolatency_set_min_lat_nsec(blkg, lat_val); |
849 | if (enable) { | ||
850 | WARN_ON_ONCE(!blk_get_queue(blkg->q)); | ||
851 | blkg_get(blkg); | ||
852 | } | ||
853 | |||
838 | if (oldval != iolat->min_lat_nsec) { | 854 | if (oldval != iolat->min_lat_nsec) { |
839 | iolatency_clear_scaling(blkg); | 855 | iolatency_clear_scaling(blkg); |
840 | } | 856 | } |
@@ -842,6 +858,24 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf, | |||
842 | ret = 0; | 858 | ret = 0; |
843 | out: | 859 | out: |
844 | blkg_conf_finish(&ctx); | 860 | blkg_conf_finish(&ctx); |
861 | if (ret == 0 && enable) { | ||
862 | struct iolatency_grp *tmp = blkg_to_lat(blkg); | ||
863 | struct blk_iolatency *blkiolat = tmp->blkiolat; | ||
864 | |||
865 | blk_mq_freeze_queue(blkg->q); | ||
866 | |||
867 | if (enable == 1) | ||
868 | atomic_inc(&blkiolat->enabled); | ||
869 | else if (enable == -1) | ||
870 | atomic_dec(&blkiolat->enabled); | ||
871 | else | ||
872 | WARN_ON_ONCE(1); | ||
873 | |||
874 | blk_mq_unfreeze_queue(blkg->q); | ||
875 | |||
876 | blkg_put(blkg); | ||
877 | blk_put_queue(blkg->q); | ||
878 | } | ||
845 | return ret ?: nbytes; | 879 | return ret ?: nbytes; |
846 | } | 880 | } |
847 | 881 | ||
@@ -977,8 +1011,14 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd) | |||
977 | { | 1011 | { |
978 | struct iolatency_grp *iolat = pd_to_lat(pd); | 1012 | struct iolatency_grp *iolat = pd_to_lat(pd); |
979 | struct blkcg_gq *blkg = lat_to_blkg(iolat); | 1013 | struct blkcg_gq *blkg = lat_to_blkg(iolat); |
1014 | struct blk_iolatency *blkiolat = iolat->blkiolat; | ||
1015 | int ret; | ||
980 | 1016 | ||
981 | iolatency_set_min_lat_nsec(blkg, 0); | 1017 | ret = iolatency_set_min_lat_nsec(blkg, 0); |
1018 | if (ret == 1) | ||
1019 | atomic_inc(&blkiolat->enabled); | ||
1020 | if (ret == -1) | ||
1021 | atomic_dec(&blkiolat->enabled); | ||
982 | iolatency_clear_scaling(blkg); | 1022 | iolatency_clear_scaling(blkg); |
983 | } | 1023 | } |
984 | 1024 | ||