1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/ioprio.h>
14#include <linux/kdev_t.h>
15#include <linux/module.h>
16#include <linux/err.h>
17#include <linux/blkdev.h>
18#include <linux/slab.h>
19#include <linux/genhd.h>
20#include <linux/delay.h>
21#include <linux/atomic.h>
22#include "blk-cgroup.h"
23#include "blk.h"
24
25#define MAX_KEY_LEN 100
26
27static DEFINE_MUTEX(blkcg_pol_mutex);
28
29struct blkcg blkcg_root = { .cfq_weight = 2 * CFQ_WEIGHT_DEFAULT,
30 .cfq_leaf_weight = 2 * CFQ_WEIGHT_DEFAULT, };
31EXPORT_SYMBOL_GPL(blkcg_root);
32
33static struct blkcg_policy *blkcg_policy[BLKCG_MAX_POLS];
34
35static bool blkcg_policy_enabled(struct request_queue *q,
36 const struct blkcg_policy *pol)
37{
38 return pol && test_bit(pol->plid, q->blkcg_pols);
39}
40
41
42
43
44
45
46
47static void blkg_free(struct blkcg_gq *blkg)
48{
49 int i;
50
51 if (!blkg)
52 return;
53
54 for (i = 0; i < BLKCG_MAX_POLS; i++)
55 kfree(blkg->pd[i]);
56
57 blk_exit_rl(&blkg->rl);
58 kfree(blkg);
59}
60
61
62
63
64
65
66
67
68
69static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q,
70 gfp_t gfp_mask)
71{
72 struct blkcg_gq *blkg;
73 int i;
74
75
76 blkg = kzalloc_node(sizeof(*blkg), gfp_mask, q->node);
77 if (!blkg)
78 return NULL;
79
80 blkg->q = q;
81 INIT_LIST_HEAD(&blkg->q_node);
82 blkg->blkcg = blkcg;
83 blkg->refcnt = 1;
84
85
86 if (blkcg != &blkcg_root) {
87 if (blk_init_rl(&blkg->rl, q, gfp_mask))
88 goto err_free;
89 blkg->rl.blkg = blkg;
90 }
91
92 for (i = 0; i < BLKCG_MAX_POLS; i++) {
93 struct blkcg_policy *pol = blkcg_policy[i];
94 struct blkg_policy_data *pd;
95
96 if (!blkcg_policy_enabled(q, pol))
97 continue;
98
99
100 pd = kzalloc_node(pol->pd_size, gfp_mask, q->node);
101 if (!pd)
102 goto err_free;
103
104 blkg->pd[i] = pd;
105 pd->blkg = blkg;
106 pd->plid = i;
107 }
108
109 return blkg;
110
111err_free:
112 blkg_free(blkg);
113 return NULL;
114}
115
116
117
118
119
120
121
122
123
124
125
126
127struct blkcg_gq *__blkg_lookup(struct blkcg *blkcg, struct request_queue *q,
128 bool update_hint)
129{
130 struct blkcg_gq *blkg;
131
132 blkg = rcu_dereference(blkcg->blkg_hint);
133 if (blkg && blkg->q == q)
134 return blkg;
135
136
137
138
139
140
141
142 blkg = radix_tree_lookup(&blkcg->blkg_tree, q->id);
143 if (blkg && blkg->q == q) {
144 if (update_hint) {
145 lockdep_assert_held(q->queue_lock);
146 rcu_assign_pointer(blkcg->blkg_hint, blkg);
147 }
148 return blkg;
149 }
150
151 return NULL;
152}
153
154
155
156
157
158
159
160
161
162
163struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, struct request_queue *q)
164{
165 WARN_ON_ONCE(!rcu_read_lock_held());
166
167 if (unlikely(blk_queue_bypass(q)))
168 return NULL;
169 return __blkg_lookup(blkcg, q, false);
170}
171EXPORT_SYMBOL_GPL(blkg_lookup);
172
173
174
175
176
177static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
178 struct request_queue *q,
179 struct blkcg_gq *new_blkg)
180{
181 struct blkcg_gq *blkg;
182 int i, ret;
183
184 WARN_ON_ONCE(!rcu_read_lock_held());
185 lockdep_assert_held(q->queue_lock);
186
187
188 if (!css_tryget(&blkcg->css)) {
189 ret = -EINVAL;
190 goto err_free_blkg;
191 }
192
193
194 if (!new_blkg) {
195 new_blkg = blkg_alloc(blkcg, q, GFP_ATOMIC);
196 if (unlikely(!new_blkg)) {
197 ret = -ENOMEM;
198 goto err_put_css;
199 }
200 }
201 blkg = new_blkg;
202
203
204 if (blkcg_parent(blkcg)) {
205 blkg->parent = __blkg_lookup(blkcg_parent(blkcg), q, false);
206 if (WARN_ON_ONCE(!blkg->parent)) {
207 ret = -EINVAL;
208 goto err_put_css;
209 }
210 blkg_get(blkg->parent);
211 }
212
213
214 for (i = 0; i < BLKCG_MAX_POLS; i++) {
215 struct blkcg_policy *pol = blkcg_policy[i];
216
217 if (blkg->pd[i] && pol->pd_init_fn)
218 pol->pd_init_fn(blkg);
219 }
220
221
222 spin_lock(&blkcg->lock);
223 ret = radix_tree_insert(&blkcg->blkg_tree, q->id, blkg);
224 if (likely(!ret)) {
225 hlist_add_head_rcu(&blkg->blkcg_node, &blkcg->blkg_list);
226 list_add(&blkg->q_node, &q->blkg_list);
227
228 for (i = 0; i < BLKCG_MAX_POLS; i++) {
229 struct blkcg_policy *pol = blkcg_policy[i];
230
231 if (blkg->pd[i] && pol->pd_online_fn)
232 pol->pd_online_fn(blkg);
233 }
234 }
235 blkg->online = true;
236 spin_unlock(&blkcg->lock);
237
238 if (!ret)
239 return blkg;
240
241
242 blkg_put(blkg);
243 return ERR_PTR(ret);
244
245err_put_css:
246 css_put(&blkcg->css);
247err_free_blkg:
248 blkg_free(new_blkg);
249 return ERR_PTR(ret);
250}
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
267 struct request_queue *q)
268{
269 struct blkcg_gq *blkg;
270
271 WARN_ON_ONCE(!rcu_read_lock_held());
272 lockdep_assert_held(q->queue_lock);
273
274
275
276
277
278 if (unlikely(blk_queue_bypass(q)))
279 return ERR_PTR(blk_queue_dying(q) ? -EINVAL : -EBUSY);
280
281 blkg = __blkg_lookup(blkcg, q, true);
282 if (blkg)
283 return blkg;
284
285
286
287
288
289 while (true) {
290 struct blkcg *pos = blkcg;
291 struct blkcg *parent = blkcg_parent(blkcg);
292
293 while (parent && !__blkg_lookup(parent, q, false)) {
294 pos = parent;
295 parent = blkcg_parent(parent);
296 }
297
298 blkg = blkg_create(pos, q, NULL);
299 if (pos == blkcg || IS_ERR(blkg))
300 return blkg;
301 }
302}
303EXPORT_SYMBOL_GPL(blkg_lookup_create);
304
305static void blkg_destroy(struct blkcg_gq *blkg)
306{
307 struct blkcg *blkcg = blkg->blkcg;
308 int i;
309
310 lockdep_assert_held(blkg->q->queue_lock);
311 lockdep_assert_held(&blkcg->lock);
312
313
314 WARN_ON_ONCE(list_empty(&blkg->q_node));
315 WARN_ON_ONCE(hlist_unhashed(&blkg->blkcg_node));
316
317 for (i = 0; i < BLKCG_MAX_POLS; i++) {
318 struct blkcg_policy *pol = blkcg_policy[i];
319
320 if (blkg->pd[i] && pol->pd_offline_fn)
321 pol->pd_offline_fn(blkg);
322 }
323 blkg->online = false;
324
325 radix_tree_delete(&blkcg->blkg_tree, blkg->q->id);
326 list_del_init(&blkg->q_node);
327 hlist_del_init_rcu(&blkg->blkcg_node);
328
329
330
331
332
333
334 if (rcu_dereference_raw(blkcg->blkg_hint) == blkg)
335 rcu_assign_pointer(blkcg->blkg_hint, NULL);
336
337
338
339
340
341 blkg_put(blkg);
342}
343
344
345
346
347
348
349
350static void blkg_destroy_all(struct request_queue *q)
351{
352 struct blkcg_gq *blkg, *n;
353
354 lockdep_assert_held(q->queue_lock);
355
356 list_for_each_entry_safe(blkg, n, &q->blkg_list, q_node) {
357 struct blkcg *blkcg = blkg->blkcg;
358
359 spin_lock(&blkcg->lock);
360 blkg_destroy(blkg);
361 spin_unlock(&blkcg->lock);
362 }
363
364
365
366
367
368 q->root_blkg = NULL;
369 q->root_rl.blkg = NULL;
370}
371
372
373
374
375
376
377
378
379
380void __blkg_release_rcu(struct rcu_head *rcu_head)
381{
382 struct blkcg_gq *blkg = container_of(rcu_head, struct blkcg_gq, rcu_head);
383 int i;
384
385
386 for (i = 0; i < BLKCG_MAX_POLS; i++) {
387 struct blkcg_policy *pol = blkcg_policy[i];
388
389 if (blkg->pd[i] && pol->pd_exit_fn)
390 pol->pd_exit_fn(blkg);
391 }
392
393
394 css_put(&blkg->blkcg->css);
395 if (blkg->parent) {
396 spin_lock_irq(blkg->q->queue_lock);
397 blkg_put(blkg->parent);
398 spin_unlock_irq(blkg->q->queue_lock);
399 }
400
401 blkg_free(blkg);
402}
403EXPORT_SYMBOL_GPL(__blkg_release_rcu);
404
405
406
407
408
409struct request_list *__blk_queue_next_rl(struct request_list *rl,
410 struct request_queue *q)
411{
412 struct list_head *ent;
413 struct blkcg_gq *blkg;
414
415
416
417
418
419 if (rl == &q->root_rl) {
420 ent = &q->blkg_list;
421
422 if (list_empty(ent))
423 return NULL;
424 } else {
425 blkg = container_of(rl, struct blkcg_gq, rl);
426 ent = &blkg->q_node;
427 }
428
429
430 ent = ent->next;
431 if (ent == &q->root_blkg->q_node)
432 ent = ent->next;
433 if (ent == &q->blkg_list)
434 return NULL;
435
436 blkg = container_of(ent, struct blkcg_gq, q_node);
437 return &blkg->rl;
438}
439
440static int blkcg_reset_stats(struct cgroup *cgroup, struct cftype *cftype,
441 u64 val)
442{
443 struct blkcg *blkcg = cgroup_to_blkcg(cgroup);
444 struct blkcg_gq *blkg;
445 int i;
446
447 mutex_lock(&blkcg_pol_mutex);
448 spin_lock_irq(&blkcg->lock);
449
450
451
452
453
454
455 hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
456 for (i = 0; i < BLKCG_MAX_POLS; i++) {
457 struct blkcg_policy *pol = blkcg_policy[i];
458
459 if (blkcg_policy_enabled(blkg->q, pol) &&
460 pol->pd_reset_stats_fn)
461 pol->pd_reset_stats_fn(blkg);
462 }
463 }
464
465 spin_unlock_irq(&blkcg->lock);
466 mutex_unlock(&blkcg_pol_mutex);
467 return 0;
468}
469
470static const char *blkg_dev_name(struct blkcg_gq *blkg)
471{
472
473 if (blkg->q->backing_dev_info.dev)
474 return dev_name(blkg->q->backing_dev_info.dev);
475 return NULL;
476}
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496void blkcg_print_blkgs(struct seq_file *sf, struct blkcg *blkcg,
497 u64 (*prfill)(struct seq_file *,
498 struct blkg_policy_data *, int),
499 const struct blkcg_policy *pol, int data,
500 bool show_total)
501{
502 struct blkcg_gq *blkg;
503 u64 total = 0;
504
505 rcu_read_lock();
506 hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
507 spin_lock_irq(blkg->q->queue_lock);
508 if (blkcg_policy_enabled(blkg->q, pol))
509 total += prfill(sf, blkg->pd[pol->plid], data);
510 spin_unlock_irq(blkg->q->queue_lock);
511 }
512 rcu_read_unlock();
513
514 if (show_total)
515 seq_printf(sf, "Total %llu\n", (unsigned long long)total);
516}
517EXPORT_SYMBOL_GPL(blkcg_print_blkgs);
518
519
520
521
522
523
524
525
526
527u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v)
528{
529 const char *dname = blkg_dev_name(pd->blkg);
530
531 if (!dname)
532 return 0;
533
534 seq_printf(sf, "%s %llu\n", dname, (unsigned long long)v);
535 return v;
536}
537EXPORT_SYMBOL_GPL(__blkg_prfill_u64);
538
539
540
541
542
543
544
545
546
547u64 __blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,
548 const struct blkg_rwstat *rwstat)
549{
550 static const char *rwstr[] = {
551 [BLKG_RWSTAT_READ] = "Read",
552 [BLKG_RWSTAT_WRITE] = "Write",
553 [BLKG_RWSTAT_SYNC] = "Sync",
554 [BLKG_RWSTAT_ASYNC] = "Async",
555 };
556 const char *dname = blkg_dev_name(pd->blkg);
557 u64 v;
558 int i;
559
560 if (!dname)
561 return 0;
562
563 for (i = 0; i < BLKG_RWSTAT_NR; i++)
564 seq_printf(sf, "%s %s %llu\n", dname, rwstr[i],
565 (unsigned long long)rwstat->cnt[i]);
566
567 v = rwstat->cnt[BLKG_RWSTAT_READ] + rwstat->cnt[BLKG_RWSTAT_WRITE];
568 seq_printf(sf, "%s Total %llu\n", dname, (unsigned long long)v);
569 return v;
570}
571EXPORT_SYMBOL_GPL(__blkg_prfill_rwstat);
572
573
574
575
576
577
578
579
580
581u64 blkg_prfill_stat(struct seq_file *sf, struct blkg_policy_data *pd, int off)
582{
583 return __blkg_prfill_u64(sf, pd, blkg_stat_read((void *)pd + off));
584}
585EXPORT_SYMBOL_GPL(blkg_prfill_stat);
586
587
588
589
590
591
592
593
594
595u64 blkg_prfill_rwstat(struct seq_file *sf, struct blkg_policy_data *pd,
596 int off)
597{
598 struct blkg_rwstat rwstat = blkg_rwstat_read((void *)pd + off);
599
600 return __blkg_prfill_rwstat(sf, pd, &rwstat);
601}
602EXPORT_SYMBOL_GPL(blkg_prfill_rwstat);
603
604
605
606
607
608
609
610
611
612
613u64 blkg_stat_recursive_sum(struct blkg_policy_data *pd, int off)
614{
615 struct blkcg_policy *pol = blkcg_policy[pd->plid];
616 struct blkcg_gq *pos_blkg;
617 struct cgroup *pos_cgrp;
618 u64 sum;
619
620 lockdep_assert_held(pd->blkg->q->queue_lock);
621
622 sum = blkg_stat_read((void *)pd + off);
623
624 rcu_read_lock();
625 blkg_for_each_descendant_pre(pos_blkg, pos_cgrp, pd_to_blkg(pd)) {
626 struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol);
627 struct blkg_stat *stat = (void *)pos_pd + off;
628
629 if (pos_blkg->online)
630 sum += blkg_stat_read(stat);
631 }
632 rcu_read_unlock();
633
634 return sum;
635}
636EXPORT_SYMBOL_GPL(blkg_stat_recursive_sum);
637
638
639
640
641
642
643
644
645
646
647struct blkg_rwstat blkg_rwstat_recursive_sum(struct blkg_policy_data *pd,
648 int off)
649{
650 struct blkcg_policy *pol = blkcg_policy[pd->plid];
651 struct blkcg_gq *pos_blkg;
652 struct cgroup *pos_cgrp;
653 struct blkg_rwstat sum;
654 int i;
655
656 lockdep_assert_held(pd->blkg->q->queue_lock);
657
658 sum = blkg_rwstat_read((void *)pd + off);
659
660 rcu_read_lock();
661 blkg_for_each_descendant_pre(pos_blkg, pos_cgrp, pd_to_blkg(pd)) {
662 struct blkg_policy_data *pos_pd = blkg_to_pd(pos_blkg, pol);
663 struct blkg_rwstat *rwstat = (void *)pos_pd + off;
664 struct blkg_rwstat tmp;
665
666 if (!pos_blkg->online)
667 continue;
668
669 tmp = blkg_rwstat_read(rwstat);
670
671 for (i = 0; i < BLKG_RWSTAT_NR; i++)
672 sum.cnt[i] += tmp.cnt[i];
673 }
674 rcu_read_unlock();
675
676 return sum;
677}
678EXPORT_SYMBOL_GPL(blkg_rwstat_recursive_sum);
679
680
681
682
683
684
685
686
687
688
689
690
691
692int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol,
693 const char *input, struct blkg_conf_ctx *ctx)
694 __acquires(rcu) __acquires(disk->queue->queue_lock)
695{
696 struct gendisk *disk;
697 struct blkcg_gq *blkg;
698 unsigned int major, minor;
699 unsigned long long v;
700 int part, ret;
701
702 if (sscanf(input, "%u:%u %llu", &major, &minor, &v) != 3)
703 return -EINVAL;
704
705 disk = get_gendisk(MKDEV(major, minor), &part);
706 if (!disk || part)
707 return -EINVAL;
708
709 rcu_read_lock();
710 spin_lock_irq(disk->queue->queue_lock);
711
712 if (blkcg_policy_enabled(disk->queue, pol))
713 blkg = blkg_lookup_create(blkcg, disk->queue);
714 else
715 blkg = ERR_PTR(-EINVAL);
716
717 if (IS_ERR(blkg)) {
718 ret = PTR_ERR(blkg);
719 rcu_read_unlock();
720 spin_unlock_irq(disk->queue->queue_lock);
721 put_disk(disk);
722
723
724
725
726
727
728 if (ret == -EBUSY) {
729 msleep(10);
730 ret = restart_syscall();
731 }
732 return ret;
733 }
734
735 ctx->disk = disk;
736 ctx->blkg = blkg;
737 ctx->v = v;
738 return 0;
739}
740EXPORT_SYMBOL_GPL(blkg_conf_prep);
741
742
743
744
745
746
747
748
749void blkg_conf_finish(struct blkg_conf_ctx *ctx)
750 __releases(ctx->disk->queue->queue_lock) __releases(rcu)
751{
752 spin_unlock_irq(ctx->disk->queue->queue_lock);
753 rcu_read_unlock();
754 put_disk(ctx->disk);
755}
756EXPORT_SYMBOL_GPL(blkg_conf_finish);
757
758struct cftype blkcg_files[] = {
759 {
760 .name = "reset_stats",
761 .write_u64 = blkcg_reset_stats,
762 },
763 { }
764};
765
766
767
768
769
770
771
772
773
774
775
776
777static void blkcg_css_offline(struct cgroup *cgroup)
778{
779 struct blkcg *blkcg = cgroup_to_blkcg(cgroup);
780
781 spin_lock_irq(&blkcg->lock);
782
783 while (!hlist_empty(&blkcg->blkg_list)) {
784 struct blkcg_gq *blkg = hlist_entry(blkcg->blkg_list.first,
785 struct blkcg_gq, blkcg_node);
786 struct request_queue *q = blkg->q;
787
788 if (spin_trylock(q->queue_lock)) {
789 blkg_destroy(blkg);
790 spin_unlock(q->queue_lock);
791 } else {
792 spin_unlock_irq(&blkcg->lock);
793 cpu_relax();
794 spin_lock_irq(&blkcg->lock);
795 }
796 }
797
798 spin_unlock_irq(&blkcg->lock);
799}
800
801static void blkcg_css_free(struct cgroup *cgroup)
802{
803 struct blkcg *blkcg = cgroup_to_blkcg(cgroup);
804
805 if (blkcg != &blkcg_root)
806 kfree(blkcg);
807}
808
809static struct cgroup_subsys_state *blkcg_css_alloc(struct cgroup *cgroup)
810{
811 static atomic64_t id_seq = ATOMIC64_INIT(0);
812 struct blkcg *blkcg;
813 struct cgroup *parent = cgroup->parent;
814
815 if (!parent) {
816 blkcg = &blkcg_root;
817 goto done;
818 }
819
820 blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
821 if (!blkcg)
822 return ERR_PTR(-ENOMEM);
823
824 blkcg->cfq_weight = CFQ_WEIGHT_DEFAULT;
825 blkcg->cfq_leaf_weight = CFQ_WEIGHT_DEFAULT;
826 blkcg->id = atomic64_inc_return(&id_seq);
827done:
828 spin_lock_init(&blkcg->lock);
829 INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_ATOMIC);
830 INIT_HLIST_HEAD(&blkcg->blkg_list);
831
832 return &blkcg->css;
833}
834
835
836
837
838
839
840
841
842
843
844
845int blkcg_init_queue(struct request_queue *q)
846{
847 might_sleep();
848
849 return blk_throtl_init(q);
850}
851
852
853
854
855
856
857
858void blkcg_drain_queue(struct request_queue *q)
859{
860 lockdep_assert_held(q->queue_lock);
861
862 blk_throtl_drain(q);
863}
864
865
866
867
868
869
870
871void blkcg_exit_queue(struct request_queue *q)
872{
873 spin_lock_irq(q->queue_lock);
874 blkg_destroy_all(q);
875 spin_unlock_irq(q->queue_lock);
876
877 blk_throtl_exit(q);
878}
879
880
881
882
883
884
885
886static int blkcg_can_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
887{
888 struct task_struct *task;
889 struct io_context *ioc;
890 int ret = 0;
891
892
893 cgroup_taskset_for_each(task, cgrp, tset) {
894 task_lock(task);
895 ioc = task->io_context;
896 if (ioc && atomic_read(&ioc->nr_tasks) > 1)
897 ret = -EINVAL;
898 task_unlock(task);
899 if (ret)
900 break;
901 }
902 return ret;
903}
904
905struct cgroup_subsys blkio_subsys = {
906 .name = "blkio",
907 .css_alloc = blkcg_css_alloc,
908 .css_offline = blkcg_css_offline,
909 .css_free = blkcg_css_free,
910 .can_attach = blkcg_can_attach,
911 .subsys_id = blkio_subsys_id,
912 .base_cftypes = blkcg_files,
913 .module = THIS_MODULE,
914};
915EXPORT_SYMBOL_GPL(blkio_subsys);
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933int blkcg_activate_policy(struct request_queue *q,
934 const struct blkcg_policy *pol)
935{
936 LIST_HEAD(pds);
937 struct blkcg_gq *blkg, *new_blkg;
938 struct blkg_policy_data *pd, *n;
939 int cnt = 0, ret;
940 bool preloaded;
941
942 if (blkcg_policy_enabled(q, pol))
943 return 0;
944
945
946 new_blkg = blkg_alloc(&blkcg_root, q, GFP_KERNEL);
947 if (!new_blkg)
948 return -ENOMEM;
949
950 blk_queue_bypass_start(q);
951
952 preloaded = !radix_tree_preload(GFP_KERNEL);
953
954
955
956
957
958
959 spin_lock_irq(q->queue_lock);
960
961 rcu_read_lock();
962 blkg = __blkg_lookup(&blkcg_root, q, false);
963 if (blkg)
964 blkg_free(new_blkg);
965 else
966 blkg = blkg_create(&blkcg_root, q, new_blkg);
967 rcu_read_unlock();
968
969 if (preloaded)
970 radix_tree_preload_end();
971
972 if (IS_ERR(blkg)) {
973 ret = PTR_ERR(blkg);
974 goto out_unlock;
975 }
976 q->root_blkg = blkg;
977 q->root_rl.blkg = blkg;
978
979 list_for_each_entry(blkg, &q->blkg_list, q_node)
980 cnt++;
981
982 spin_unlock_irq(q->queue_lock);
983
984
985 while (cnt--) {
986 pd = kzalloc_node(pol->pd_size, GFP_KERNEL, q->node);
987 if (!pd) {
988 ret = -ENOMEM;
989 goto out_free;
990 }
991 list_add_tail(&pd->alloc_node, &pds);
992 }
993
994
995
996
997
998 spin_lock_irq(q->queue_lock);
999
1000 list_for_each_entry(blkg, &q->blkg_list, q_node) {
1001 if (WARN_ON(list_empty(&pds))) {
1002
1003 ret = -ENOMEM;
1004 goto out_unlock;
1005 }
1006 pd = list_first_entry(&pds, struct blkg_policy_data, alloc_node);
1007 list_del_init(&pd->alloc_node);
1008
1009
1010 spin_lock(&blkg->blkcg->lock);
1011
1012 blkg->pd[pol->plid] = pd;
1013 pd->blkg = blkg;
1014 pd->plid = pol->plid;
1015 pol->pd_init_fn(blkg);
1016
1017 spin_unlock(&blkg->blkcg->lock);
1018 }
1019
1020 __set_bit(pol->plid, q->blkcg_pols);
1021 ret = 0;
1022out_unlock:
1023 spin_unlock_irq(q->queue_lock);
1024out_free:
1025 blk_queue_bypass_end(q);
1026 list_for_each_entry_safe(pd, n, &pds, alloc_node)
1027 kfree(pd);
1028 return ret;
1029}
1030EXPORT_SYMBOL_GPL(blkcg_activate_policy);
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040void blkcg_deactivate_policy(struct request_queue *q,
1041 const struct blkcg_policy *pol)
1042{
1043 struct blkcg_gq *blkg;
1044
1045 if (!blkcg_policy_enabled(q, pol))
1046 return;
1047
1048 blk_queue_bypass_start(q);
1049 spin_lock_irq(q->queue_lock);
1050
1051 __clear_bit(pol->plid, q->blkcg_pols);
1052
1053
1054 if (bitmap_empty(q->blkcg_pols, BLKCG_MAX_POLS))
1055 blkg_destroy_all(q);
1056
1057 list_for_each_entry(blkg, &q->blkg_list, q_node) {
1058
1059 spin_lock(&blkg->blkcg->lock);
1060
1061 if (pol->pd_offline_fn)
1062 pol->pd_offline_fn(blkg);
1063 if (pol->pd_exit_fn)
1064 pol->pd_exit_fn(blkg);
1065
1066 kfree(blkg->pd[pol->plid]);
1067 blkg->pd[pol->plid] = NULL;
1068
1069 spin_unlock(&blkg->blkcg->lock);
1070 }
1071
1072 spin_unlock_irq(q->queue_lock);
1073 blk_queue_bypass_end(q);
1074}
1075EXPORT_SYMBOL_GPL(blkcg_deactivate_policy);
1076
1077
1078
1079
1080
1081
1082
1083
1084int blkcg_policy_register(struct blkcg_policy *pol)
1085{
1086 int i, ret;
1087
1088 if (WARN_ON(pol->pd_size < sizeof(struct blkg_policy_data)))
1089 return -EINVAL;
1090
1091 mutex_lock(&blkcg_pol_mutex);
1092
1093
1094 ret = -ENOSPC;
1095 for (i = 0; i < BLKCG_MAX_POLS; i++)
1096 if (!blkcg_policy[i])
1097 break;
1098 if (i >= BLKCG_MAX_POLS)
1099 goto out_unlock;
1100
1101
1102 pol->plid = i;
1103 blkcg_policy[i] = pol;
1104
1105
1106 if (pol->cftypes)
1107 WARN_ON(cgroup_add_cftypes(&blkio_subsys, pol->cftypes));
1108 ret = 0;
1109out_unlock:
1110 mutex_unlock(&blkcg_pol_mutex);
1111 return ret;
1112}
1113EXPORT_SYMBOL_GPL(blkcg_policy_register);
1114
1115
1116
1117
1118
1119
1120
1121void blkcg_policy_unregister(struct blkcg_policy *pol)
1122{
1123 mutex_lock(&blkcg_pol_mutex);
1124
1125 if (WARN_ON(blkcg_policy[pol->plid] != pol))
1126 goto out_unlock;
1127
1128
1129 if (pol->cftypes)
1130 cgroup_rm_cftypes(&blkio_subsys, pol->cftypes);
1131
1132
1133 blkcg_policy[pol->plid] = NULL;
1134out_unlock:
1135 mutex_unlock(&blkcg_pol_mutex);
1136}
1137EXPORT_SYMBOL_GPL(blkcg_policy_unregister);
1138