diff options
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r-- | block/blk-throttle.c | 153 |
1 files changed, 58 insertions, 95 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 27f7960dd421..004964bb6fdd 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
@@ -924,20 +924,6 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay) | |||
924 | } | 924 | } |
925 | } | 925 | } |
926 | 926 | ||
927 | /* | ||
928 | * Can not take queue lock in update functions as queue lock under | ||
929 | * blkcg_lock is not allowed. Under other paths we take blkcg_lock under | ||
930 | * queue_lock. | ||
931 | */ | ||
932 | static void throtl_update_blkio_group_common(struct throtl_data *td, | ||
933 | struct throtl_grp *tg) | ||
934 | { | ||
935 | xchg(&tg->limits_changed, true); | ||
936 | xchg(&td->limits_changed, true); | ||
937 | /* Schedule a work now to process the limit change */ | ||
938 | throtl_schedule_delayed_work(td, 0); | ||
939 | } | ||
940 | |||
941 | static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, | 927 | static u64 tg_prfill_cpu_rwstat(struct seq_file *sf, |
942 | struct blkg_policy_data *pd, int off) | 928 | struct blkg_policy_data *pd, int off) |
943 | { | 929 | { |
@@ -968,68 +954,48 @@ static int tg_print_cpu_rwstat(struct cgroup *cgrp, struct cftype *cft, | |||
968 | return 0; | 954 | return 0; |
969 | } | 955 | } |
970 | 956 | ||
971 | static u64 blkg_prfill_conf_u64(struct seq_file *sf, | 957 | static u64 tg_prfill_conf_u64(struct seq_file *sf, struct blkg_policy_data *pd, |
972 | struct blkg_policy_data *pd, int off) | 958 | int off) |
973 | { | 959 | { |
974 | u64 v = *(u64 *)((void *)&pd->conf + off); | 960 | u64 v = *(u64 *)((void *)pd->pdata + off); |
975 | 961 | ||
976 | if (!v) | 962 | if (v == -1) |
977 | return 0; | 963 | return 0; |
978 | return __blkg_prfill_u64(sf, pd, v); | 964 | return __blkg_prfill_u64(sf, pd, v); |
979 | } | 965 | } |
980 | 966 | ||
981 | static int blkcg_print_conf_u64(struct cgroup *cgrp, struct cftype *cft, | 967 | static u64 tg_prfill_conf_uint(struct seq_file *sf, struct blkg_policy_data *pd, |
982 | struct seq_file *sf) | 968 | int off) |
983 | { | 969 | { |
984 | blkcg_print_blkgs(sf, cgroup_to_blkio_cgroup(cgrp), | 970 | unsigned int v = *(unsigned int *)((void *)pd->pdata + off); |
985 | blkg_prfill_conf_u64, BLKIO_POLICY_THROTL, | ||
986 | cft->private, false); | ||
987 | return 0; | ||
988 | } | ||
989 | 971 | ||
990 | static void throtl_update_blkio_group_read_bps(struct blkio_group *blkg, | 972 | if (v == -1) |
991 | u64 read_bps) | 973 | return 0; |
992 | { | 974 | return __blkg_prfill_u64(sf, pd, v); |
993 | struct throtl_grp *tg = blkg_to_tg(blkg); | ||
994 | |||
995 | tg->bps[READ] = read_bps; | ||
996 | throtl_update_blkio_group_common(blkg->q->td, tg); | ||
997 | } | ||
998 | |||
999 | static void throtl_update_blkio_group_write_bps(struct blkio_group *blkg, | ||
1000 | u64 write_bps) | ||
1001 | { | ||
1002 | struct throtl_grp *tg = blkg_to_tg(blkg); | ||
1003 | |||
1004 | tg->bps[WRITE] = write_bps; | ||
1005 | throtl_update_blkio_group_common(blkg->q->td, tg); | ||
1006 | } | 975 | } |
1007 | 976 | ||
1008 | static void throtl_update_blkio_group_read_iops(struct blkio_group *blkg, | 977 | static int tg_print_conf_u64(struct cgroup *cgrp, struct cftype *cft, |
1009 | u64 read_iops) | 978 | struct seq_file *sf) |
1010 | { | 979 | { |
1011 | struct throtl_grp *tg = blkg_to_tg(blkg); | 980 | blkcg_print_blkgs(sf, cgroup_to_blkio_cgroup(cgrp), tg_prfill_conf_u64, |
1012 | 981 | BLKIO_POLICY_THROTL, cft->private, false); | |
1013 | tg->iops[READ] = read_iops; | 982 | return 0; |
1014 | throtl_update_blkio_group_common(blkg->q->td, tg); | ||
1015 | } | 983 | } |
1016 | 984 | ||
1017 | static void throtl_update_blkio_group_write_iops(struct blkio_group *blkg, | 985 | static int tg_print_conf_uint(struct cgroup *cgrp, struct cftype *cft, |
1018 | u64 write_iops) | 986 | struct seq_file *sf) |
1019 | { | 987 | { |
1020 | struct throtl_grp *tg = blkg_to_tg(blkg); | 988 | blkcg_print_blkgs(sf, cgroup_to_blkio_cgroup(cgrp), tg_prfill_conf_uint, |
1021 | 989 | BLKIO_POLICY_THROTL, cft->private, false); | |
1022 | tg->iops[WRITE] = write_iops; | 990 | return 0; |
1023 | throtl_update_blkio_group_common(blkg->q->td, tg); | ||
1024 | } | 991 | } |
1025 | 992 | ||
1026 | static int blkcg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft, | 993 | static int tg_set_conf(struct cgroup *cgrp, struct cftype *cft, const char *buf, |
1027 | const char *buf, | 994 | bool is_u64) |
1028 | void (*update)(struct blkio_group *, u64)) | ||
1029 | { | 995 | { |
1030 | struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgrp); | 996 | struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgrp); |
1031 | struct blkg_policy_data *pd; | ||
1032 | struct blkg_conf_ctx ctx; | 997 | struct blkg_conf_ctx ctx; |
998 | struct throtl_grp *tg; | ||
1033 | int ret; | 999 | int ret; |
1034 | 1000 | ||
1035 | ret = blkg_conf_prep(blkcg, buf, &ctx); | 1001 | ret = blkg_conf_prep(blkcg, buf, &ctx); |
@@ -1037,10 +1003,23 @@ static int blkcg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft, | |||
1037 | return ret; | 1003 | return ret; |
1038 | 1004 | ||
1039 | ret = -EINVAL; | 1005 | ret = -EINVAL; |
1040 | pd = ctx.blkg->pd[BLKIO_POLICY_THROTL]; | 1006 | tg = blkg_to_tg(ctx.blkg); |
1041 | if (pd) { | 1007 | if (tg) { |
1042 | *(u64 *)((void *)&pd->conf + cft->private) = ctx.v; | 1008 | struct throtl_data *td = ctx.blkg->q->td; |
1043 | update(ctx.blkg, ctx.v ?: -1); | 1009 | |
1010 | if (!ctx.v) | ||
1011 | ctx.v = -1; | ||
1012 | |||
1013 | if (is_u64) | ||
1014 | *(u64 *)((void *)tg + cft->private) = ctx.v; | ||
1015 | else | ||
1016 | *(unsigned int *)((void *)tg + cft->private) = ctx.v; | ||
1017 | |||
1018 | /* XXX: we don't need the following deferred processing */ | ||
1019 | xchg(&tg->limits_changed, true); | ||
1020 | xchg(&td->limits_changed, true); | ||
1021 | throtl_schedule_delayed_work(td, 0); | ||
1022 | |||
1044 | ret = 0; | 1023 | ret = 0; |
1045 | } | 1024 | } |
1046 | 1025 | ||
@@ -1048,61 +1027,45 @@ static int blkcg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft, | |||
1048 | return ret; | 1027 | return ret; |
1049 | } | 1028 | } |
1050 | 1029 | ||
1051 | static int blkcg_set_conf_bps_r(struct cgroup *cgrp, struct cftype *cft, | 1030 | static int tg_set_conf_u64(struct cgroup *cgrp, struct cftype *cft, |
1052 | const char *buf) | 1031 | const char *buf) |
1053 | { | ||
1054 | return blkcg_set_conf_u64(cgrp, cft, buf, | ||
1055 | throtl_update_blkio_group_read_bps); | ||
1056 | } | ||
1057 | |||
1058 | static int blkcg_set_conf_bps_w(struct cgroup *cgrp, struct cftype *cft, | ||
1059 | const char *buf) | ||
1060 | { | ||
1061 | return blkcg_set_conf_u64(cgrp, cft, buf, | ||
1062 | throtl_update_blkio_group_write_bps); | ||
1063 | } | ||
1064 | |||
1065 | static int blkcg_set_conf_iops_r(struct cgroup *cgrp, struct cftype *cft, | ||
1066 | const char *buf) | ||
1067 | { | 1032 | { |
1068 | return blkcg_set_conf_u64(cgrp, cft, buf, | 1033 | return tg_set_conf(cgrp, cft, buf, true); |
1069 | throtl_update_blkio_group_read_iops); | ||
1070 | } | 1034 | } |
1071 | 1035 | ||
1072 | static int blkcg_set_conf_iops_w(struct cgroup *cgrp, struct cftype *cft, | 1036 | static int tg_set_conf_uint(struct cgroup *cgrp, struct cftype *cft, |
1073 | const char *buf) | 1037 | const char *buf) |
1074 | { | 1038 | { |
1075 | return blkcg_set_conf_u64(cgrp, cft, buf, | 1039 | return tg_set_conf(cgrp, cft, buf, false); |
1076 | throtl_update_blkio_group_write_iops); | ||
1077 | } | 1040 | } |
1078 | 1041 | ||
1079 | static struct cftype throtl_files[] = { | 1042 | static struct cftype throtl_files[] = { |
1080 | { | 1043 | { |
1081 | .name = "throttle.read_bps_device", | 1044 | .name = "throttle.read_bps_device", |
1082 | .private = offsetof(struct blkio_group_conf, bps[READ]), | 1045 | .private = offsetof(struct throtl_grp, bps[READ]), |
1083 | .read_seq_string = blkcg_print_conf_u64, | 1046 | .read_seq_string = tg_print_conf_u64, |
1084 | .write_string = blkcg_set_conf_bps_r, | 1047 | .write_string = tg_set_conf_u64, |
1085 | .max_write_len = 256, | 1048 | .max_write_len = 256, |
1086 | }, | 1049 | }, |
1087 | { | 1050 | { |
1088 | .name = "throttle.write_bps_device", | 1051 | .name = "throttle.write_bps_device", |
1089 | .private = offsetof(struct blkio_group_conf, bps[WRITE]), | 1052 | .private = offsetof(struct throtl_grp, bps[WRITE]), |
1090 | .read_seq_string = blkcg_print_conf_u64, | 1053 | .read_seq_string = tg_print_conf_u64, |
1091 | .write_string = blkcg_set_conf_bps_w, | 1054 | .write_string = tg_set_conf_u64, |
1092 | .max_write_len = 256, | 1055 | .max_write_len = 256, |
1093 | }, | 1056 | }, |
1094 | { | 1057 | { |
1095 | .name = "throttle.read_iops_device", | 1058 | .name = "throttle.read_iops_device", |
1096 | .private = offsetof(struct blkio_group_conf, iops[READ]), | 1059 | .private = offsetof(struct throtl_grp, iops[READ]), |
1097 | .read_seq_string = blkcg_print_conf_u64, | 1060 | .read_seq_string = tg_print_conf_uint, |
1098 | .write_string = blkcg_set_conf_iops_r, | 1061 | .write_string = tg_set_conf_uint, |
1099 | .max_write_len = 256, | 1062 | .max_write_len = 256, |
1100 | }, | 1063 | }, |
1101 | { | 1064 | { |
1102 | .name = "throttle.write_iops_device", | 1065 | .name = "throttle.write_iops_device", |
1103 | .private = offsetof(struct blkio_group_conf, iops[WRITE]), | 1066 | .private = offsetof(struct throtl_grp, iops[WRITE]), |
1104 | .read_seq_string = blkcg_print_conf_u64, | 1067 | .read_seq_string = tg_print_conf_uint, |
1105 | .write_string = blkcg_set_conf_iops_w, | 1068 | .write_string = tg_set_conf_uint, |
1106 | .max_write_len = 256, | 1069 | .max_write_len = 256, |
1107 | }, | 1070 | }, |
1108 | { | 1071 | { |