aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo2012-03-05 15:15:14 -0600
committerJens Axboe2012-03-06 14:27:23 -0600
commit0381411e4b1a52cee134eb73750e5e3cc1155d09 (patch)
tree32aa1d0b8a2ca8277e60e8b78dd731d193440924 /block/blk-throttle.c
parent923adde1be1df57cebd80c563058e503376645e8 (diff)
downloadkernel-common-0381411e4b1a52cee134eb73750e5e3cc1155d09.tar.gz
kernel-common-0381411e4b1a52cee134eb73750e5e3cc1155d09.tar.xz
kernel-common-0381411e4b1a52cee134eb73750e5e3cc1155d09.zip
blkcg: let blkcg core handle policy private data allocation
Currently, blkg's are embedded in private data blkcg policy private data structure and thus allocated and freed by policies. This leads to duplicate codes in policies, hinders implementing common part in blkcg core with strong semantics, and forces duplicate blkg's for the same cgroup-q association. This patch introduces struct blkg_policy_data which is a separate data structure chained from blkg. Policies specifies the amount of private data it needs in its blkio_policy_type->pdata_size and blkcg core takes care of allocating them along with blkg which can be accessed using blkg_to_pdata(). blkg can be determined from pdata using pdata_to_blkg(). blkio_alloc_group_fn() method is accordingly updated to blkio_init_group_fn(). For consistency, tg_of_blkg() and cfqg_of_blkg() are replaced with blkg_to_tg() and blkg_to_cfqg() respectively, and functions to map in the reverse direction are added. Except that policy specific data now lives in a separate data structure from blkg, this patch doesn't introduce any functional difference. This will be used to unify blkg's for different policies. 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.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index ac6d0fe6e4e..9c8a12477e1 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -21,6 +21,8 @@ static int throtl_quantum = 32;
21/* Throttling is performed over 100ms slice and after that slice is renewed */ 21/* Throttling is performed over 100ms slice and after that slice is renewed */
22static unsigned long throtl_slice = HZ/10; /* 100 ms */ 22static unsigned long throtl_slice = HZ/10; /* 100 ms */
23 23
24static struct blkio_policy_type blkio_policy_throtl;
25
24/* A workqueue to queue throttle related work */ 26/* A workqueue to queue throttle related work */
25static struct workqueue_struct *kthrotld_workqueue; 27static struct workqueue_struct *kthrotld_workqueue;
26static void throtl_schedule_delayed_work(struct throtl_data *td, 28static void throtl_schedule_delayed_work(struct throtl_data *td,
@@ -52,7 +54,6 @@ struct throtl_grp {
52 */ 54 */
53 unsigned long disptime; 55 unsigned long disptime;
54 56
55 struct blkio_group blkg;
56 atomic_t ref; 57 atomic_t ref;
57 unsigned int flags; 58 unsigned int flags;
58 59
@@ -108,6 +109,16 @@ struct throtl_data
108 int limits_changed; 109 int limits_changed;
109}; 110};
110 111
112static inline struct throtl_grp *blkg_to_tg(struct blkio_group *blkg)
113{
114 return blkg_to_pdata(blkg, &blkio_policy_throtl);
115}
116
117static inline struct blkio_group *tg_to_blkg(struct throtl_grp *tg)
118{
119 return pdata_to_blkg(tg, &blkio_policy_throtl);
120}
121
111enum tg_state_flags { 122enum tg_state_flags {
112 THROTL_TG_FLAG_on_rr = 0, /* on round-robin busy list */ 123 THROTL_TG_FLAG_on_rr = 0, /* on round-robin busy list */
113}; 124};
@@ -130,19 +141,11 @@ THROTL_TG_FNS(on_rr);
130 141
131#define throtl_log_tg(td, tg, fmt, args...) \ 142#define throtl_log_tg(td, tg, fmt, args...) \
132 blk_add_trace_msg((td)->queue, "throtl %s " fmt, \ 143 blk_add_trace_msg((td)->queue, "throtl %s " fmt, \
133 blkg_path(&(tg)->blkg), ##args); \ 144 blkg_path(tg_to_blkg(tg)), ##args); \
134 145
135#define throtl_log(td, fmt, args...) \ 146#define throtl_log(td, fmt, args...) \
136 blk_add_trace_msg((td)->queue, "throtl " fmt, ##args) 147 blk_add_trace_msg((td)->queue, "throtl " fmt, ##args)
137 148
138static inline struct throtl_grp *tg_of_blkg(struct blkio_group *blkg)
139{
140 if (blkg)
141 return container_of(blkg, struct throtl_grp, blkg);
142
143 return NULL;
144}
145
146static inline unsigned int total_nr_queued(struct throtl_data *td) 149static inline unsigned int total_nr_queued(struct throtl_data *td)
147{ 150{
148 return td->nr_queued[0] + td->nr_queued[1]; 151 return td->nr_queued[0] + td->nr_queued[1];
@@ -156,21 +159,24 @@ static inline struct throtl_grp *throtl_ref_get_tg(struct throtl_grp *tg)
156 159
157static void throtl_free_tg(struct rcu_head *head) 160static void throtl_free_tg(struct rcu_head *head)
158{ 161{
159 struct throtl_grp *tg; 162 struct throtl_grp *tg = container_of(head, struct throtl_grp, rcu_head);
163 struct blkio_group *blkg = tg_to_blkg(tg);
160 164
161 tg = container_of(head, struct throtl_grp, rcu_head); 165 free_percpu(blkg->stats_cpu);
162 free_percpu(tg->blkg.stats_cpu); 166 kfree(blkg->pd);
163 kfree(tg); 167 kfree(blkg);
164} 168}
165 169
166static void throtl_put_tg(struct throtl_grp *tg) 170static void throtl_put_tg(struct throtl_grp *tg)
167{ 171{
172 struct blkio_group *blkg = tg_to_blkg(tg);
173
168 BUG_ON(atomic_read(&tg->ref) <= 0); 174 BUG_ON(atomic_read(&tg->ref) <= 0);
169 if (!atomic_dec_and_test(&tg->ref)) 175 if (!atomic_dec_and_test(&tg->ref))
170 return; 176 return;
171 177
172 /* release the extra blkcg reference this blkg has been holding */ 178 /* release the extra blkcg reference this blkg has been holding */
173 css_put(&tg->blkg.blkcg->css); 179 css_put(&blkg->blkcg->css);
174 180
175 /* 181 /*
176 * A group is freed in rcu manner. But having an rcu lock does not 182 * A group is freed in rcu manner. But having an rcu lock does not
@@ -184,14 +190,9 @@ static void throtl_put_tg(struct throtl_grp *tg)
184 call_rcu(&tg->rcu_head, throtl_free_tg); 190 call_rcu(&tg->rcu_head, throtl_free_tg);
185} 191}
186 192
187static struct blkio_group *throtl_alloc_blkio_group(struct request_queue *q, 193static void throtl_init_blkio_group(struct blkio_group *blkg)
188 struct blkio_cgroup *blkcg)
189{ 194{
190 struct throtl_grp *tg; 195 struct throtl_grp *tg = blkg_to_tg(blkg);
191
192 tg = kzalloc_node(sizeof(*tg), GFP_ATOMIC, q->node);
193 if (!tg)
194 return NULL;
195 196
196 INIT_HLIST_NODE(&tg->tg_node); 197 INIT_HLIST_NODE(&tg->tg_node);
197 RB_CLEAR_NODE(&tg->rb_node); 198 RB_CLEAR_NODE(&tg->rb_node);
@@ -211,15 +212,13 @@ static struct blkio_group *throtl_alloc_blkio_group(struct request_queue *q,
211 * exit or cgroup deletion path depending on who is exiting first. 212 * exit or cgroup deletion path depending on who is exiting first.
212 */ 213 */
213 atomic_set(&tg->ref, 1); 214 atomic_set(&tg->ref, 1);
214
215 return &tg->blkg;
216} 215}
217 216
218static void throtl_link_blkio_group(struct request_queue *q, 217static void throtl_link_blkio_group(struct request_queue *q,
219 struct blkio_group *blkg) 218 struct blkio_group *blkg)
220{ 219{
221 struct throtl_data *td = q->td; 220 struct throtl_data *td = q->td;
222 struct throtl_grp *tg = tg_of_blkg(blkg); 221 struct throtl_grp *tg = blkg_to_tg(blkg);
223 222
224 hlist_add_head(&tg->tg_node, &td->tg_list); 223 hlist_add_head(&tg->tg_node, &td->tg_list);
225 td->nr_undestroyed_grps++; 224 td->nr_undestroyed_grps++;
@@ -235,7 +234,7 @@ throtl_grp *throtl_lookup_tg(struct throtl_data *td, struct blkio_cgroup *blkcg)
235 if (blkcg == &blkio_root_cgroup) 234 if (blkcg == &blkio_root_cgroup)
236 return td->root_tg; 235 return td->root_tg;
237 236
238 return tg_of_blkg(blkg_lookup(blkcg, td->queue, BLKIO_POLICY_THROTL)); 237 return blkg_to_tg(blkg_lookup(blkcg, td->queue, BLKIO_POLICY_THROTL));
239} 238}
240 239
241static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td, 240static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td,
@@ -257,7 +256,7 @@ static struct throtl_grp *throtl_lookup_create_tg(struct throtl_data *td,
257 256
258 /* if %NULL and @q is alive, fall back to root_tg */ 257 /* if %NULL and @q is alive, fall back to root_tg */
259 if (!IS_ERR(blkg)) 258 if (!IS_ERR(blkg))
260 tg = tg_of_blkg(blkg); 259 tg = blkg_to_tg(blkg);
261 else if (!blk_queue_dead(q)) 260 else if (!blk_queue_dead(q))
262 tg = td->root_tg; 261 tg = td->root_tg;
263 } 262 }
@@ -639,7 +638,7 @@ static void throtl_charge_bio(struct throtl_grp *tg, struct bio *bio)
639 tg->bytes_disp[rw] += bio->bi_size; 638 tg->bytes_disp[rw] += bio->bi_size;
640 tg->io_disp[rw]++; 639 tg->io_disp[rw]++;
641 640
642 blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, rw, sync); 641 blkiocg_update_dispatch_stats(tg_to_blkg(tg), bio->bi_size, rw, sync);
643} 642}
644 643
645static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg, 644static void throtl_add_bio_tg(struct throtl_data *td, struct throtl_grp *tg,
@@ -901,7 +900,7 @@ static bool throtl_release_tgs(struct throtl_data *td, bool release_root)
901 * it from cgroup list, then it will take care of destroying 900 * it from cgroup list, then it will take care of destroying
902 * cfqg also. 901 * cfqg also.
903 */ 902 */
904 if (!blkiocg_del_blkio_group(&tg->blkg)) 903 if (!blkiocg_del_blkio_group(tg_to_blkg(tg)))
905 throtl_destroy_tg(td, tg); 904 throtl_destroy_tg(td, tg);
906 else 905 else
907 empty = false; 906 empty = false;
@@ -929,7 +928,7 @@ void throtl_unlink_blkio_group(struct request_queue *q,
929 unsigned long flags; 928 unsigned long flags;
930 929
931 spin_lock_irqsave(q->queue_lock, flags); 930 spin_lock_irqsave(q->queue_lock, flags);
932 throtl_destroy_tg(q->td, tg_of_blkg(blkg)); 931 throtl_destroy_tg(q->td, blkg_to_tg(blkg));
933 spin_unlock_irqrestore(q->queue_lock, flags); 932 spin_unlock_irqrestore(q->queue_lock, flags);
934} 933}
935 934
@@ -968,7 +967,7 @@ static void throtl_update_blkio_group_common(struct throtl_data *td,
968static void throtl_update_blkio_group_read_bps(struct request_queue *q, 967static void throtl_update_blkio_group_read_bps(struct request_queue *q,
969 struct blkio_group *blkg, u64 read_bps) 968 struct blkio_group *blkg, u64 read_bps)
970{ 969{
971 struct throtl_grp *tg = tg_of_blkg(blkg); 970 struct throtl_grp *tg = blkg_to_tg(blkg);
972 971
973 tg->bps[READ] = read_bps; 972 tg->bps[READ] = read_bps;
974 throtl_update_blkio_group_common(q->td, tg); 973 throtl_update_blkio_group_common(q->td, tg);
@@ -977,7 +976,7 @@ static void throtl_update_blkio_group_read_bps(struct request_queue *q,
977static void throtl_update_blkio_group_write_bps(struct request_queue *q, 976static void throtl_update_blkio_group_write_bps(struct request_queue *q,
978 struct blkio_group *blkg, u64 write_bps) 977 struct blkio_group *blkg, u64 write_bps)
979{ 978{
980 struct throtl_grp *tg = tg_of_blkg(blkg); 979 struct throtl_grp *tg = blkg_to_tg(blkg);
981 980
982 tg->bps[WRITE] = write_bps; 981 tg->bps[WRITE] = write_bps;
983 throtl_update_blkio_group_common(q->td, tg); 982 throtl_update_blkio_group_common(q->td, tg);
@@ -986,7 +985,7 @@ static void throtl_update_blkio_group_write_bps(struct request_queue *q,
986static void throtl_update_blkio_group_read_iops(struct request_queue *q, 985static void throtl_update_blkio_group_read_iops(struct request_queue *q,
987 struct blkio_group *blkg, unsigned int read_iops) 986 struct blkio_group *blkg, unsigned int read_iops)
988{ 987{
989 struct throtl_grp *tg = tg_of_blkg(blkg); 988 struct throtl_grp *tg = blkg_to_tg(blkg);
990 989
991 tg->iops[READ] = read_iops; 990 tg->iops[READ] = read_iops;
992 throtl_update_blkio_group_common(q->td, tg); 991 throtl_update_blkio_group_common(q->td, tg);
@@ -995,7 +994,7 @@ static void throtl_update_blkio_group_read_iops(struct request_queue *q,
995static void throtl_update_blkio_group_write_iops(struct request_queue *q, 994static void throtl_update_blkio_group_write_iops(struct request_queue *q,
996 struct blkio_group *blkg, unsigned int write_iops) 995 struct blkio_group *blkg, unsigned int write_iops)
997{ 996{
998 struct throtl_grp *tg = tg_of_blkg(blkg); 997 struct throtl_grp *tg = blkg_to_tg(blkg);
999 998
1000 tg->iops[WRITE] = write_iops; 999 tg->iops[WRITE] = write_iops;
1001 throtl_update_blkio_group_common(q->td, tg); 1000 throtl_update_blkio_group_common(q->td, tg);
@@ -1010,7 +1009,7 @@ static void throtl_shutdown_wq(struct request_queue *q)
1010 1009
1011static struct blkio_policy_type blkio_policy_throtl = { 1010static struct blkio_policy_type blkio_policy_throtl = {
1012 .ops = { 1011 .ops = {
1013 .blkio_alloc_group_fn = throtl_alloc_blkio_group, 1012 .blkio_init_group_fn = throtl_init_blkio_group,
1014 .blkio_link_group_fn = throtl_link_blkio_group, 1013 .blkio_link_group_fn = throtl_link_blkio_group,
1015 .blkio_unlink_group_fn = throtl_unlink_blkio_group, 1014 .blkio_unlink_group_fn = throtl_unlink_blkio_group,
1016 .blkio_clear_queue_fn = throtl_clear_queue, 1015 .blkio_clear_queue_fn = throtl_clear_queue,
@@ -1024,6 +1023,7 @@ static struct blkio_policy_type blkio_policy_throtl = {
1024 throtl_update_blkio_group_write_iops, 1023 throtl_update_blkio_group_write_iops,
1025 }, 1024 },
1026 .plid = BLKIO_POLICY_THROTL, 1025 .plid = BLKIO_POLICY_THROTL,
1026 .pdata_size = sizeof(struct throtl_grp),
1027}; 1027};
1028 1028
1029bool blk_throtl_bio(struct request_queue *q, struct bio *bio) 1029bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
@@ -1049,8 +1049,9 @@ bool blk_throtl_bio(struct request_queue *q, struct bio *bio)
1049 tg = throtl_lookup_tg(td, blkcg); 1049 tg = throtl_lookup_tg(td, blkcg);
1050 if (tg) { 1050 if (tg) {
1051 if (tg_no_rule_group(tg, rw)) { 1051 if (tg_no_rule_group(tg, rw)) {
1052 blkiocg_update_dispatch_stats(&tg->blkg, bio->bi_size, 1052 blkiocg_update_dispatch_stats(tg_to_blkg(tg),
1053 rw, rw_is_sync(bio->bi_rw)); 1053 bio->bi_size, rw,
1054 rw_is_sync(bio->bi_rw));
1054 goto out_unlock_rcu; 1055 goto out_unlock_rcu;
1055 } 1056 }
1056 } 1057 }
@@ -1176,7 +1177,7 @@ int blk_throtl_init(struct request_queue *q)
1176 blkg = blkg_lookup_create(&blkio_root_cgroup, q, BLKIO_POLICY_THROTL, 1177 blkg = blkg_lookup_create(&blkio_root_cgroup, q, BLKIO_POLICY_THROTL,
1177 true); 1178 true);
1178 if (!IS_ERR(blkg)) 1179 if (!IS_ERR(blkg))
1179 td->root_tg = tg_of_blkg(blkg); 1180 td->root_tg = blkg_to_tg(blkg);
1180 1181
1181 spin_unlock_irq(q->queue_lock); 1182 spin_unlock_irq(q->queue_lock);
1182 rcu_read_unlock(); 1183 rcu_read_unlock();
@@ -1207,7 +1208,7 @@ void blk_throtl_exit(struct request_queue *q)
1207 spin_unlock_irq(q->queue_lock); 1208 spin_unlock_irq(q->queue_lock);
1208 1209
1209 /* 1210 /*
1210 * Wait for tg->blkg->q accessors to exit their grace periods. 1211 * Wait for tg_to_blkg(tg)->q accessors to exit their grace periods.
1211 * Do this wait only if there are other undestroyed groups out 1212 * Do this wait only if there are other undestroyed groups out
1212 * there (other than root group). This can happen if cgroup deletion 1213 * there (other than root group). This can happen if cgroup deletion
1213 * path claimed the responsibility of cleaning up a group before 1214 * path claimed the responsibility of cleaning up a group before