diff options
-rw-r--r-- | block/blk-cgroup.c | 145 | ||||
-rw-r--r-- | block/blk-cgroup.h | 30 |
2 files changed, 167 insertions, 8 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 7762987fdf9..aae8c930a6f 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -128,6 +128,27 @@ blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight) | |||
128 | } | 128 | } |
129 | } | 129 | } |
130 | 130 | ||
131 | static inline void blkio_update_group_bps(struct blkio_group *blkg, u64 bps, | ||
132 | int fileid) | ||
133 | { | ||
134 | struct blkio_policy_type *blkiop; | ||
135 | |||
136 | list_for_each_entry(blkiop, &blkio_list, list) { | ||
137 | |||
138 | /* If this policy does not own the blkg, do not send updates */ | ||
139 | if (blkiop->plid != blkg->plid) | ||
140 | continue; | ||
141 | |||
142 | if (fileid == BLKIO_THROTL_read_bps_device | ||
143 | && blkiop->ops.blkio_update_group_read_bps_fn) | ||
144 | blkiop->ops.blkio_update_group_read_bps_fn(blkg, bps); | ||
145 | |||
146 | if (fileid == BLKIO_THROTL_write_bps_device | ||
147 | && blkiop->ops.blkio_update_group_write_bps_fn) | ||
148 | blkiop->ops.blkio_update_group_write_bps_fn(blkg, bps); | ||
149 | } | ||
150 | } | ||
151 | |||
131 | /* | 152 | /* |
132 | * Add to the appropriate stat variable depending on the request type. | 153 | * Add to the appropriate stat variable depending on the request type. |
133 | * This should be called with the blkg->stats_lock held. | 154 | * This should be called with the blkg->stats_lock held. |
@@ -612,6 +633,7 @@ static int blkio_policy_parse_and_set(char *buf, | |||
612 | unsigned long major, minor, temp; | 633 | unsigned long major, minor, temp; |
613 | int i = 0; | 634 | int i = 0; |
614 | dev_t dev; | 635 | dev_t dev; |
636 | u64 bps; | ||
615 | 637 | ||
616 | memset(s, 0, sizeof(s)); | 638 | memset(s, 0, sizeof(s)); |
617 | 639 | ||
@@ -667,7 +689,16 @@ static int blkio_policy_parse_and_set(char *buf, | |||
667 | 689 | ||
668 | newpn->plid = plid; | 690 | newpn->plid = plid; |
669 | newpn->fileid = fileid; | 691 | newpn->fileid = fileid; |
670 | newpn->weight = temp; | 692 | newpn->val.weight = temp; |
693 | break; | ||
694 | case BLKIO_POLICY_THROTL: | ||
695 | ret = strict_strtoull(s[1], 10, &bps); | ||
696 | if (ret) | ||
697 | return -EINVAL; | ||
698 | |||
699 | newpn->plid = plid; | ||
700 | newpn->fileid = fileid; | ||
701 | newpn->val.bps = bps; | ||
671 | break; | 702 | break; |
672 | default: | 703 | default: |
673 | BUG(); | 704 | BUG(); |
@@ -684,18 +715,45 @@ unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, | |||
684 | pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP, | 715 | pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_PROP, |
685 | BLKIO_PROP_weight_device); | 716 | BLKIO_PROP_weight_device); |
686 | if (pn) | 717 | if (pn) |
687 | return pn->weight; | 718 | return pn->val.weight; |
688 | else | 719 | else |
689 | return blkcg->weight; | 720 | return blkcg->weight; |
690 | } | 721 | } |
691 | EXPORT_SYMBOL_GPL(blkcg_get_weight); | 722 | EXPORT_SYMBOL_GPL(blkcg_get_weight); |
692 | 723 | ||
724 | uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, dev_t dev) | ||
725 | { | ||
726 | struct blkio_policy_node *pn; | ||
727 | |||
728 | pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL, | ||
729 | BLKIO_THROTL_read_bps_device); | ||
730 | if (pn) | ||
731 | return pn->val.bps; | ||
732 | else | ||
733 | return -1; | ||
734 | } | ||
735 | |||
736 | uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, dev_t dev) | ||
737 | { | ||
738 | struct blkio_policy_node *pn; | ||
739 | pn = blkio_policy_search_node(blkcg, dev, BLKIO_POLICY_THROTL, | ||
740 | BLKIO_THROTL_write_bps_device); | ||
741 | if (pn) | ||
742 | return pn->val.bps; | ||
743 | else | ||
744 | return -1; | ||
745 | } | ||
746 | |||
693 | /* Checks whether user asked for deleting a policy rule */ | 747 | /* Checks whether user asked for deleting a policy rule */ |
694 | static bool blkio_delete_rule_command(struct blkio_policy_node *pn) | 748 | static bool blkio_delete_rule_command(struct blkio_policy_node *pn) |
695 | { | 749 | { |
696 | switch(pn->plid) { | 750 | switch(pn->plid) { |
697 | case BLKIO_POLICY_PROP: | 751 | case BLKIO_POLICY_PROP: |
698 | if (pn->weight == 0) | 752 | if (pn->val.weight == 0) |
753 | return 1; | ||
754 | break; | ||
755 | case BLKIO_POLICY_THROTL: | ||
756 | if (pn->val.bps == 0) | ||
699 | return 1; | 757 | return 1; |
700 | break; | 758 | break; |
701 | default: | 759 | default: |
@@ -710,7 +768,10 @@ static void blkio_update_policy_rule(struct blkio_policy_node *oldpn, | |||
710 | { | 768 | { |
711 | switch(oldpn->plid) { | 769 | switch(oldpn->plid) { |
712 | case BLKIO_POLICY_PROP: | 770 | case BLKIO_POLICY_PROP: |
713 | oldpn->weight = newpn->weight; | 771 | oldpn->val.weight = newpn->val.weight; |
772 | break; | ||
773 | case BLKIO_POLICY_THROTL: | ||
774 | oldpn->val.bps = newpn->val.bps; | ||
714 | break; | 775 | break; |
715 | default: | 776 | default: |
716 | BUG(); | 777 | BUG(); |
@@ -725,13 +786,23 @@ static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg, | |||
725 | struct blkio_group *blkg, struct blkio_policy_node *pn) | 786 | struct blkio_group *blkg, struct blkio_policy_node *pn) |
726 | { | 787 | { |
727 | unsigned int weight; | 788 | unsigned int weight; |
789 | u64 bps; | ||
728 | 790 | ||
729 | switch(pn->plid) { | 791 | switch(pn->plid) { |
730 | case BLKIO_POLICY_PROP: | 792 | case BLKIO_POLICY_PROP: |
731 | weight = pn->weight ? pn->weight : | 793 | weight = pn->val.weight ? pn->val.weight : |
732 | blkcg->weight; | 794 | blkcg->weight; |
733 | blkio_update_group_weight(blkg, weight); | 795 | blkio_update_group_weight(blkg, weight); |
734 | break; | 796 | break; |
797 | case BLKIO_POLICY_THROTL: | ||
798 | switch(pn->fileid) { | ||
799 | case BLKIO_THROTL_read_bps_device: | ||
800 | case BLKIO_THROTL_write_bps_device: | ||
801 | bps = pn->val.bps ? pn->val.bps : (-1); | ||
802 | blkio_update_group_bps(blkg, bps, pn->fileid); | ||
803 | break; | ||
804 | } | ||
805 | break; | ||
735 | default: | 806 | default: |
736 | BUG(); | 807 | BUG(); |
737 | } | 808 | } |
@@ -826,7 +897,17 @@ blkio_print_policy_node(struct seq_file *m, struct blkio_policy_node *pn) | |||
826 | case BLKIO_POLICY_PROP: | 897 | case BLKIO_POLICY_PROP: |
827 | if (pn->fileid == BLKIO_PROP_weight_device) | 898 | if (pn->fileid == BLKIO_PROP_weight_device) |
828 | seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev), | 899 | seq_printf(m, "%u:%u\t%u\n", MAJOR(pn->dev), |
829 | MINOR(pn->dev), pn->weight); | 900 | MINOR(pn->dev), pn->val.weight); |
901 | break; | ||
902 | case BLKIO_POLICY_THROTL: | ||
903 | if (pn->fileid == BLKIO_THROTL_read_bps_device) | ||
904 | seq_printf(m, "%u:%u\t%llu\n", MAJOR(pn->dev), | ||
905 | MINOR(pn->dev), pn->val.bps); | ||
906 | else if (pn->fileid == BLKIO_THROTL_write_bps_device) | ||
907 | seq_printf(m, "%u:%u\t%llu\n", MAJOR(pn->dev), | ||
908 | MINOR(pn->dev), pn->val.bps); | ||
909 | else | ||
910 | BUG(); | ||
830 | break; | 911 | break; |
831 | default: | 912 | default: |
832 | BUG(); | 913 | BUG(); |
@@ -869,6 +950,16 @@ static int blkiocg_file_read(struct cgroup *cgrp, struct cftype *cft, | |||
869 | BUG(); | 950 | BUG(); |
870 | } | 951 | } |
871 | break; | 952 | break; |
953 | case BLKIO_POLICY_THROTL: | ||
954 | switch(name){ | ||
955 | case BLKIO_THROTL_read_bps_device: | ||
956 | case BLKIO_THROTL_write_bps_device: | ||
957 | blkio_read_policy_node_files(cft, blkcg, m); | ||
958 | return 0; | ||
959 | default: | ||
960 | BUG(); | ||
961 | } | ||
962 | break; | ||
872 | default: | 963 | default: |
873 | BUG(); | 964 | BUG(); |
874 | } | 965 | } |
@@ -959,7 +1050,18 @@ static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft, | |||
959 | BUG(); | 1050 | BUG(); |
960 | } | 1051 | } |
961 | break; | 1052 | break; |
962 | 1053 | case BLKIO_POLICY_THROTL: | |
1054 | switch(name){ | ||
1055 | case BLKIO_THROTL_io_service_bytes: | ||
1056 | return blkio_read_blkg_stats(blkcg, cft, cb, | ||
1057 | BLKIO_STAT_SERVICE_BYTES, 1); | ||
1058 | case BLKIO_THROTL_io_serviced: | ||
1059 | return blkio_read_blkg_stats(blkcg, cft, cb, | ||
1060 | BLKIO_STAT_SERVICED, 1); | ||
1061 | default: | ||
1062 | BUG(); | ||
1063 | } | ||
1064 | break; | ||
963 | default: | 1065 | default: |
964 | BUG(); | 1066 | BUG(); |
965 | } | 1067 | } |
@@ -1053,6 +1155,23 @@ struct cftype blkio_files[] = { | |||
1053 | .write_u64 = blkiocg_file_write_u64, | 1155 | .write_u64 = blkiocg_file_write_u64, |
1054 | }, | 1156 | }, |
1055 | { | 1157 | { |
1158 | .name = "throttle.read_bps_device", | ||
1159 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL, | ||
1160 | BLKIO_THROTL_read_bps_device), | ||
1161 | .read_seq_string = blkiocg_file_read, | ||
1162 | .write_string = blkiocg_file_write, | ||
1163 | .max_write_len = 256, | ||
1164 | }, | ||
1165 | |||
1166 | { | ||
1167 | .name = "throttle.write_bps_device", | ||
1168 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL, | ||
1169 | BLKIO_THROTL_write_bps_device), | ||
1170 | .read_seq_string = blkiocg_file_read, | ||
1171 | .write_string = blkiocg_file_write, | ||
1172 | .max_write_len = 256, | ||
1173 | }, | ||
1174 | { | ||
1056 | .name = "time", | 1175 | .name = "time", |
1057 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, | 1176 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, |
1058 | BLKIO_PROP_time), | 1177 | BLKIO_PROP_time), |
@@ -1071,12 +1190,24 @@ struct cftype blkio_files[] = { | |||
1071 | .read_map = blkiocg_file_read_map, | 1190 | .read_map = blkiocg_file_read_map, |
1072 | }, | 1191 | }, |
1073 | { | 1192 | { |
1193 | .name = "throttle.io_service_bytes", | ||
1194 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL, | ||
1195 | BLKIO_THROTL_io_service_bytes), | ||
1196 | .read_map = blkiocg_file_read_map, | ||
1197 | }, | ||
1198 | { | ||
1074 | .name = "io_serviced", | 1199 | .name = "io_serviced", |
1075 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, | 1200 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, |
1076 | BLKIO_PROP_io_serviced), | 1201 | BLKIO_PROP_io_serviced), |
1077 | .read_map = blkiocg_file_read_map, | 1202 | .read_map = blkiocg_file_read_map, |
1078 | }, | 1203 | }, |
1079 | { | 1204 | { |
1205 | .name = "throttle.io_serviced", | ||
1206 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_THROTL, | ||
1207 | BLKIO_THROTL_io_serviced), | ||
1208 | .read_map = blkiocg_file_read_map, | ||
1209 | }, | ||
1210 | { | ||
1080 | .name = "io_service_time", | 1211 | .name = "io_service_time", |
1081 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, | 1212 | .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, |
1082 | BLKIO_PROP_io_service_time), | 1213 | BLKIO_PROP_io_service_time), |
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index c8de2598429..1b738827b2f 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | enum blkio_policy_id { | 18 | enum blkio_policy_id { |
19 | BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */ | 19 | BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */ |
20 | BLKIO_POLICY_THROTL, /* Throttling */ | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) | 23 | #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE) |
@@ -88,6 +89,14 @@ enum blkcg_file_name_prop { | |||
88 | BLKIO_PROP_dequeue, | 89 | BLKIO_PROP_dequeue, |
89 | }; | 90 | }; |
90 | 91 | ||
92 | /* cgroup files owned by throttle policy */ | ||
93 | enum blkcg_file_name_throtl { | ||
94 | BLKIO_THROTL_read_bps_device, | ||
95 | BLKIO_THROTL_write_bps_device, | ||
96 | BLKIO_THROTL_io_service_bytes, | ||
97 | BLKIO_THROTL_io_serviced, | ||
98 | }; | ||
99 | |||
91 | struct blkio_cgroup { | 100 | struct blkio_cgroup { |
92 | struct cgroup_subsys_state css; | 101 | struct cgroup_subsys_state css; |
93 | unsigned int weight; | 102 | unsigned int weight; |
@@ -146,23 +155,42 @@ struct blkio_group { | |||
146 | struct blkio_policy_node { | 155 | struct blkio_policy_node { |
147 | struct list_head node; | 156 | struct list_head node; |
148 | dev_t dev; | 157 | dev_t dev; |
149 | unsigned int weight; | ||
150 | /* This node belongs to max bw policy or porportional weight policy */ | 158 | /* This node belongs to max bw policy or porportional weight policy */ |
151 | enum blkio_policy_id plid; | 159 | enum blkio_policy_id plid; |
152 | /* cgroup file to which this rule belongs to */ | 160 | /* cgroup file to which this rule belongs to */ |
153 | int fileid; | 161 | int fileid; |
162 | |||
163 | union { | ||
164 | unsigned int weight; | ||
165 | /* | ||
166 | * Rate read/write in terms of byptes per second | ||
167 | * Whether this rate represents read or write is determined | ||
168 | * by file type "fileid". | ||
169 | */ | ||
170 | u64 bps; | ||
171 | } val; | ||
154 | }; | 172 | }; |
155 | 173 | ||
156 | extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, | 174 | extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, |
157 | dev_t dev); | 175 | dev_t dev); |
176 | extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg, | ||
177 | dev_t dev); | ||
178 | extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg, | ||
179 | dev_t dev); | ||
158 | 180 | ||
159 | typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg); | 181 | typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg); |
160 | typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg, | 182 | typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg, |
161 | unsigned int weight); | 183 | unsigned int weight); |
184 | typedef void (blkio_update_group_read_bps_fn) (struct blkio_group *blkg, | ||
185 | u64 read_bps); | ||
186 | typedef void (blkio_update_group_write_bps_fn) (struct blkio_group *blkg, | ||
187 | u64 write_bps); | ||
162 | 188 | ||
163 | struct blkio_policy_ops { | 189 | struct blkio_policy_ops { |
164 | blkio_unlink_group_fn *blkio_unlink_group_fn; | 190 | blkio_unlink_group_fn *blkio_unlink_group_fn; |
165 | blkio_update_group_weight_fn *blkio_update_group_weight_fn; | 191 | blkio_update_group_weight_fn *blkio_update_group_weight_fn; |
192 | blkio_update_group_read_bps_fn *blkio_update_group_read_bps_fn; | ||
193 | blkio_update_group_write_bps_fn *blkio_update_group_write_bps_fn; | ||
166 | }; | 194 | }; |
167 | 195 | ||
168 | struct blkio_policy_type { | 196 | struct blkio_policy_type { |