aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/blk-cgroup.c145
-rw-r--r--block/blk-cgroup.h30
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
131static 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}
691EXPORT_SYMBOL_GPL(blkcg_get_weight); 722EXPORT_SYMBOL_GPL(blkcg_get_weight);
692 723
724uint64_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
736uint64_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 */
694static bool blkio_delete_rule_command(struct blkio_policy_node *pn) 748static 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
18enum blkio_policy_id { 18enum 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 */
93enum 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
91struct blkio_cgroup { 100struct 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 {
146struct blkio_policy_node { 155struct 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
156extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg, 174extern unsigned int blkcg_get_weight(struct blkio_cgroup *blkcg,
157 dev_t dev); 175 dev_t dev);
176extern uint64_t blkcg_get_read_bps(struct blkio_cgroup *blkcg,
177 dev_t dev);
178extern uint64_t blkcg_get_write_bps(struct blkio_cgroup *blkcg,
179 dev_t dev);
158 180
159typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg); 181typedef void (blkio_unlink_group_fn) (void *key, struct blkio_group *blkg);
160typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg, 182typedef void (blkio_update_group_weight_fn) (struct blkio_group *blkg,
161 unsigned int weight); 183 unsigned int weight);
184typedef void (blkio_update_group_read_bps_fn) (struct blkio_group *blkg,
185 u64 read_bps);
186typedef void (blkio_update_group_write_bps_fn) (struct blkio_group *blkg,
187 u64 write_bps);
162 188
163struct blkio_policy_ops { 189struct 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
168struct blkio_policy_type { 196struct blkio_policy_type {