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