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