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 7762987fdf9e..aae8c930a6f8 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 c8de2598429d..1b738827b2f6 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 { |
