aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-throttle.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-03-05 16:15:18 -0500
committerJens Axboe <axboe@kernel.dk>2012-03-06 15:27:23 -0500
commit4eef3049986e8397d5003916aed8cad6567a5e02 (patch)
tree5e36431986907b9fa728a6fbeb819a2738a64c82 /block/blk-throttle.c
parentc1768268f9424410761da57ea71107acae7b03cc (diff)
blkcg: move per-queue blkg list heads and counters to queue and blkg
Currently, specific policy implementations are responsible for maintaining list and number of blkgs. This duplicates code unnecessarily, and hinders factoring common code and providing blkcg API with better defined semantics. After this patch, request_queue hosts list heads and counters and blkg has list nodes for both policies. This patch only relocates the necessary fields and the next patch will actually move management code into blkcg core. Note that request_queue->blkg_list[] and ->nr_blkgs[] are hardcoded to have 2 elements. This is to avoid include dependency and will be removed by the next patch. This patch doesn't introduce any behavior change. -v2: Now unnecessary conditional on CONFIG_BLK_CGROUP_MODULE removed as pointed out by Vivek. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-throttle.c')
-rw-r--r--block/blk-throttle.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index b2fddaf20b98..c15d38307e1d 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -41,9 +41,6 @@ struct throtl_rb_root {
41#define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) 41#define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node)
42 42
43struct throtl_grp { 43struct throtl_grp {
44 /* List of throtl groups on the request queue*/
45 struct hlist_node tg_node;
46
47 /* active throtl group service_tree member */ 44 /* active throtl group service_tree member */
48 struct rb_node rb_node; 45 struct rb_node rb_node;
49 46
@@ -83,9 +80,6 @@ struct throtl_grp {
83 80
84struct throtl_data 81struct throtl_data
85{ 82{
86 /* List of throtl groups */
87 struct hlist_head tg_list;
88
89 /* service tree for active throtl groups */ 83 /* service tree for active throtl groups */
90 struct throtl_rb_root tg_service_tree; 84 struct throtl_rb_root tg_service_tree;
91 85
@@ -152,7 +146,6 @@ static void throtl_init_blkio_group(struct blkio_group *blkg)
152{ 146{
153 struct throtl_grp *tg = blkg_to_tg(blkg); 147 struct throtl_grp *tg = blkg_to_tg(blkg);
154 148
155 INIT_HLIST_NODE(&tg->tg_node);
156 RB_CLEAR_NODE(&tg->rb_node); 149 RB_CLEAR_NODE(&tg->rb_node);
157 bio_list_init(&tg->bio_lists[0]); 150 bio_list_init(&tg->bio_lists[0]);
158 bio_list_init(&tg->bio_lists[1]); 151 bio_list_init(&tg->bio_lists[1]);
@@ -167,11 +160,9 @@ static void throtl_init_blkio_group(struct blkio_group *blkg)
167static void throtl_link_blkio_group(struct request_queue *q, 160static void throtl_link_blkio_group(struct request_queue *q,
168 struct blkio_group *blkg) 161 struct blkio_group *blkg)
169{ 162{
170 struct throtl_data *td = q->td; 163 list_add(&blkg->q_node[BLKIO_POLICY_THROTL],
171 struct throtl_grp *tg = blkg_to_tg(blkg); 164 &q->blkg_list[BLKIO_POLICY_THROTL]);
172 165 q->nr_blkgs[BLKIO_POLICY_THROTL]++;
173 hlist_add_head(&tg->tg_node, &td->tg_list);
174 td->nr_undestroyed_grps++;
175} 166}
176 167
177static struct 168static struct
@@ -711,8 +702,8 @@ static int throtl_select_dispatch(struct throtl_data *td, struct bio_list *bl)
711 702
712static void throtl_process_limit_change(struct throtl_data *td) 703static void throtl_process_limit_change(struct throtl_data *td)
713{ 704{
714 struct throtl_grp *tg; 705 struct request_queue *q = td->queue;
715 struct hlist_node *pos, *n; 706 struct blkio_group *blkg, *n;
716 707
717 if (!td->limits_changed) 708 if (!td->limits_changed)
718 return; 709 return;
@@ -721,7 +712,10 @@ static void throtl_process_limit_change(struct throtl_data *td)
721 712
722 throtl_log(td, "limits changed"); 713 throtl_log(td, "limits changed");
723 714
724 hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { 715 list_for_each_entry_safe(blkg, n, &q->blkg_list[BLKIO_POLICY_THROTL],
716 q_node[BLKIO_POLICY_THROTL]) {
717 struct throtl_grp *tg = blkg_to_tg(blkg);
718
725 if (!tg->limits_changed) 719 if (!tg->limits_changed)
726 continue; 720 continue;
727 721
@@ -822,26 +816,31 @@ throtl_schedule_delayed_work(struct throtl_data *td, unsigned long delay)
822static void 816static void
823throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg) 817throtl_destroy_tg(struct throtl_data *td, struct throtl_grp *tg)
824{ 818{
819 struct blkio_group *blkg = tg_to_blkg(tg);
820
825 /* Something wrong if we are trying to remove same group twice */ 821 /* Something wrong if we are trying to remove same group twice */
826 BUG_ON(hlist_unhashed(&tg->tg_node)); 822 WARN_ON_ONCE(list_empty(&blkg->q_node[BLKIO_POLICY_THROTL]));
827 823
828 hlist_del_init(&tg->tg_node); 824 list_del_init(&blkg->q_node[BLKIO_POLICY_THROTL]);
829 825
830 /* 826 /*
831 * Put the reference taken at the time of creation so that when all 827 * Put the reference taken at the time of creation so that when all
832 * queues are gone, group can be destroyed. 828 * queues are gone, group can be destroyed.
833 */ 829 */
834 blkg_put(tg_to_blkg(tg)); 830 blkg_put(tg_to_blkg(tg));
835 td->nr_undestroyed_grps--; 831 td->queue->nr_blkgs[BLKIO_POLICY_THROTL]--;
836} 832}
837 833
838static bool throtl_release_tgs(struct throtl_data *td, bool release_root) 834static bool throtl_release_tgs(struct throtl_data *td, bool release_root)
839{ 835{
840 struct hlist_node *pos, *n; 836 struct request_queue *q = td->queue;
841 struct throtl_grp *tg; 837 struct blkio_group *blkg, *n;
842 bool empty = true; 838 bool empty = true;
843 839
844 hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) { 840 list_for_each_entry_safe(blkg, n, &q->blkg_list[BLKIO_POLICY_THROTL],
841 q_node[BLKIO_POLICY_THROTL]) {
842 struct throtl_grp *tg = blkg_to_tg(blkg);
843
845 /* skip root? */ 844 /* skip root? */
846 if (!release_root && tg == td->root_tg) 845 if (!release_root && tg == td->root_tg)
847 continue; 846 continue;
@@ -851,7 +850,7 @@ static bool throtl_release_tgs(struct throtl_data *td, bool release_root)
851 * it from cgroup list, then it will take care of destroying 850 * it from cgroup list, then it will take care of destroying
852 * cfqg also. 851 * cfqg also.
853 */ 852 */
854 if (!blkiocg_del_blkio_group(tg_to_blkg(tg))) 853 if (!blkiocg_del_blkio_group(blkg))
855 throtl_destroy_tg(td, tg); 854 throtl_destroy_tg(td, tg);
856 else 855 else
857 empty = false; 856 empty = false;
@@ -1114,7 +1113,6 @@ int blk_throtl_init(struct request_queue *q)
1114 if (!td) 1113 if (!td)
1115 return -ENOMEM; 1114 return -ENOMEM;
1116 1115
1117 INIT_HLIST_HEAD(&td->tg_list);
1118 td->tg_service_tree = THROTL_RB_ROOT; 1116 td->tg_service_tree = THROTL_RB_ROOT;
1119 td->limits_changed = false; 1117 td->limits_changed = false;
1120 INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work); 1118 INIT_DELAYED_WORK(&td->throtl_work, blk_throtl_work);
@@ -1144,7 +1142,7 @@ int blk_throtl_init(struct request_queue *q)
1144void blk_throtl_exit(struct request_queue *q) 1142void blk_throtl_exit(struct request_queue *q)
1145{ 1143{
1146 struct throtl_data *td = q->td; 1144 struct throtl_data *td = q->td;
1147 bool wait = false; 1145 bool wait;
1148 1146
1149 BUG_ON(!td); 1147 BUG_ON(!td);
1150 1148
@@ -1154,8 +1152,7 @@ void blk_throtl_exit(struct request_queue *q)
1154 throtl_release_tgs(td, true); 1152 throtl_release_tgs(td, true);
1155 1153
1156 /* If there are other groups */ 1154 /* If there are other groups */
1157 if (td->nr_undestroyed_grps > 0) 1155 wait = q->nr_blkgs[BLKIO_POLICY_THROTL];
1158 wait = true;
1159 1156
1160 spin_unlock_irq(q->queue_lock); 1157 spin_unlock_irq(q->queue_lock);
1161 1158