Merge tag 'zynq-soc-for-v5.15' of https://github.com/Xilinx/linux-xlnx into arm/defconfig
[linux-2.6-microblaze.git] / block / mq-deadline-cgroup.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/blk-cgroup.h>
4 #include <linux/ioprio.h>
5
6 #include "mq-deadline-cgroup.h"
7
8 static struct blkcg_policy dd_blkcg_policy;
9
10 static struct blkcg_policy_data *dd_cpd_alloc(gfp_t gfp)
11 {
12         struct dd_blkcg *pd;
13
14         pd = kzalloc(sizeof(*pd), gfp);
15         if (!pd)
16                 return NULL;
17         pd->stats = alloc_percpu_gfp(typeof(*pd->stats),
18                                      GFP_KERNEL | __GFP_ZERO);
19         if (!pd->stats) {
20                 kfree(pd);
21                 return NULL;
22         }
23         return &pd->cpd;
24 }
25
26 static void dd_cpd_free(struct blkcg_policy_data *cpd)
27 {
28         struct dd_blkcg *dd_blkcg = container_of(cpd, typeof(*dd_blkcg), cpd);
29
30         free_percpu(dd_blkcg->stats);
31         kfree(dd_blkcg);
32 }
33
34 static struct dd_blkcg *dd_blkcg_from_pd(struct blkg_policy_data *pd)
35 {
36         return container_of(blkcg_to_cpd(pd->blkg->blkcg, &dd_blkcg_policy),
37                             struct dd_blkcg, cpd);
38 }
39
40 /*
41  * Convert an association between a block cgroup and a request queue into a
42  * pointer to the mq-deadline information associated with a (blkcg, queue) pair.
43  */
44 struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
45 {
46         struct blkg_policy_data *pd;
47
48         pd = blkg_to_pd(bio->bi_blkg, &dd_blkcg_policy);
49         if (!pd)
50                 return NULL;
51
52         return dd_blkcg_from_pd(pd);
53 }
54
55 static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
56 {
57         static const char *const prio_class_name[] = {
58                 [IOPRIO_CLASS_NONE]     = "NONE",
59                 [IOPRIO_CLASS_RT]       = "RT",
60                 [IOPRIO_CLASS_BE]       = "BE",
61                 [IOPRIO_CLASS_IDLE]     = "IDLE",
62         };
63         struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd);
64         int res = 0;
65         u8 prio;
66
67         for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++)
68                 res += scnprintf(buf + res, size - res,
69                         " [%s] dispatched=%u inserted=%u merged=%u",
70                         prio_class_name[prio],
71                         ddcg_sum(blkcg, dispatched, prio) +
72                         ddcg_sum(blkcg, merged, prio) -
73                         ddcg_sum(blkcg, completed, prio),
74                         ddcg_sum(blkcg, inserted, prio) -
75                         ddcg_sum(blkcg, completed, prio),
76                         ddcg_sum(blkcg, merged, prio));
77
78         return res;
79 }
80
81 static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q,
82                                             struct blkcg *blkcg)
83 {
84         struct dd_blkg *pd;
85
86         pd = kzalloc(sizeof(*pd), gfp);
87         if (!pd)
88                 return NULL;
89         return &pd->pd;
90 }
91
92 static void dd_pd_free(struct blkg_policy_data *pd)
93 {
94         struct dd_blkg *dd_blkg = container_of(pd, typeof(*dd_blkg), pd);
95
96         kfree(dd_blkg);
97 }
98
99 static struct blkcg_policy dd_blkcg_policy = {
100         .cpd_alloc_fn           = dd_cpd_alloc,
101         .cpd_free_fn            = dd_cpd_free,
102
103         .pd_alloc_fn            = dd_pd_alloc,
104         .pd_free_fn             = dd_pd_free,
105         .pd_stat_fn             = dd_pd_stat,
106 };
107
108 int dd_activate_policy(struct request_queue *q)
109 {
110         return blkcg_activate_policy(q, &dd_blkcg_policy);
111 }
112
113 void dd_deactivate_policy(struct request_queue *q)
114 {
115         blkcg_deactivate_policy(q, &dd_blkcg_policy);
116 }
117
118 int __init dd_blkcg_init(void)
119 {
120         return blkcg_policy_register(&dd_blkcg_policy);
121 }
122
123 void __exit dd_blkcg_exit(void)
124 {
125         blkcg_policy_unregister(&dd_blkcg_policy);
126 }