summaryrefslogtreecommitdiffstats
path: root/block/blk-iolatency.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-iolatency.c')
-rw-r--r--block/blk-iolatency.c56
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
757static 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 */
767static 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
774static void iolatency_clear_scaling(struct blkcg_gq *blkg) 784static 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;
843out: 859out:
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