• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dd_cpd_alloc(gfp_t gfp)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 
dd_cpd_free(struct blkcg_policy_data * cpd)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 
dd_blkcg_from_pd(struct blkg_policy_data * pd)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  */
dd_blkcg_from_bio(struct bio * bio)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 
dd_pd_stat(struct blkg_policy_data * pd,char * buf,size_t size)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 
dd_pd_alloc(gfp_t gfp,struct request_queue * q,struct blkcg * blkcg)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 
dd_pd_free(struct blkg_policy_data * pd)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 
dd_activate_policy(struct request_queue * q)108 int dd_activate_policy(struct request_queue *q)
109 {
110 	return blkcg_activate_policy(q, &dd_blkcg_policy);
111 }
112 
dd_deactivate_policy(struct request_queue * q)113 void dd_deactivate_policy(struct request_queue *q)
114 {
115 	blkcg_deactivate_policy(q, &dd_blkcg_policy);
116 }
117 
dd_blkcg_init(void)118 int __init dd_blkcg_init(void)
119 {
120 	return blkcg_policy_register(&dd_blkcg_policy);
121 }
122 
dd_blkcg_exit(void)123 void __exit dd_blkcg_exit(void)
124 {
125 	blkcg_policy_unregister(&dd_blkcg_policy);
126 }
127