blob: 3b4bfddec39f31fb220f7c0d2496caae2bb8c051 [file] [log] [blame]
Bart Van Assche855265c2021-06-11 16:48:32 -07001// 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
8static struct blkcg_policy dd_blkcg_policy;
9
10static 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
26static 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
34static 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 */
44struct 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
55static 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
81static 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
92static 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
99static 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
108int dd_activate_policy(struct request_queue *q)
109{
110 return blkcg_activate_policy(q, &dd_blkcg_policy);
111}
112
113void dd_deactivate_policy(struct request_queue *q)
114{
115 blkcg_deactivate_policy(q, &dd_blkcg_policy);
116}
117
118int __init dd_blkcg_init(void)
119{
120 return blkcg_policy_register(&dd_blkcg_policy);
121}
122
123void __exit dd_blkcg_exit(void)
124{
125 blkcg_policy_unregister(&dd_blkcg_policy);
126}