aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-iolatency.c52
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
757static 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 */
765static 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
774static void iolatency_clear_scaling(struct blkcg_gq *blkg) 782static 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;
843out: 857out:
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