// SPDX-License-Identifier: GPL-2.0
/*
* Block rq - qos policy for assigning an I / O priority class to requests .
*
* Using an rq - qos policy for assigning I / O priority class has two advantages
* over using the ioprio_set ( ) system call :
*
* - This policy is cgroup based so it has all the advantages of cgroups .
* - While ioprio_set ( ) does not affect page cache writeback I / O , this rq - qos
* controller affects page cache writeback I / O for filesystems that support
* assiociating a cgroup with writeback I / O . See also
* Documentation / admin - guide / cgroup - v2 . rst .
*/
#include <linux/blk-mq.h>
#include <linux/blk_types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include "blk-cgroup.h"
#include "blk-ioprio.h"
#include "blk-rq-qos.h"
/**
* enum prio_policy - I / O priority class policy .
* @ POLICY_NO_CHANGE : ( default ) do not modify the I / O priority class .
* @ POLICY_PROMOTE_TO_RT : modify no - IOPRIO_CLASS_RT to IOPRIO_CLASS_RT .
* @ POLICY_RESTRICT_TO_BE : modify IOPRIO_CLASS_NONE and IOPRIO_CLASS_RT into
* IOPRIO_CLASS_BE .
* @ POLICY_ALL_TO_IDLE : change the I / O priority class into IOPRIO_CLASS_IDLE .
* @ POLICY_NONE_TO_RT : an alias for POLICY_PROMOTE_TO_RT .
*
* See also < linux / ioprio . h > .
*/
enum prio_policy {
POLICY_NO_CHANGE = 0 ,
POLICY_PROMOTE_TO_RT = 1 ,
POLICY_RESTRICT_TO_BE = 2 ,
POLICY_ALL_TO_IDLE = 3 ,
POLICY_NONE_TO_RT = 4 ,
};
static const char *policy_name[] = {
[POLICY_NO_CHANGE] = "no-change" ,
[POLICY_PROMOTE_TO_RT] = "promote-to-rt" ,
[POLICY_RESTRICT_TO_BE] = "restrict-to-be" ,
[POLICY_ALL_TO_IDLE] = "idle" ,
[POLICY_NONE_TO_RT] = "none-to-rt" ,
};
static struct blkcg_policy ioprio_policy;
/**
* struct ioprio_blkcg - Per cgroup data .
* @ cpd : blkcg_policy_data structure .
* @ prio_policy : One of the IOPRIO_CLASS_ * values . See also < linux / ioprio . h > .
*/
struct ioprio_blkcg {
struct blkcg_policy_data cpd;
enum prio_policy prio_policy;
};
static struct ioprio_blkcg *blkcg_to_ioprio_blkcg(struct blkcg *blkcg)
{
return container_of(blkcg_to_cpd(blkcg, &ioprio_policy),
struct ioprio_blkcg, cpd);
}
static struct ioprio_blkcg *
ioprio_blkcg_from_css(struct cgroup_subsys_state *css)
{
return blkcg_to_ioprio_blkcg(css_to_blkcg(css));
}
static int ioprio_show_prio_policy(struct seq_file *sf, void *v)
{
struct ioprio_blkcg *blkcg = ioprio_blkcg_from_css(seq_css(sf));
seq_printf(sf, "%s\n" , policy_name[blkcg->prio_policy]);
return 0 ;
}
static ssize_t ioprio_set_prio_policy(struct kernfs_open_file *of, char *buf,
size_t nbytes, loff_t off)
{
struct ioprio_blkcg *blkcg = ioprio_blkcg_from_css(of_css(of));
int ret;
if (off != 0 )
return -EIO;
/* kernfs_fop_write_iter() terminates 'buf' with '\0'. */
ret = sysfs_match_string(policy_name, buf);
if (ret < 0 )
return ret;
blkcg->prio_policy = ret;
return nbytes;
}
static struct blkcg_policy_data *ioprio_alloc_cpd(gfp_t gfp)
{
struct ioprio_blkcg *blkcg;
blkcg = kzalloc(sizeof (*blkcg), gfp);
if (!blkcg)
return NULL;
blkcg->prio_policy = POLICY_NO_CHANGE;
return &blkcg->cpd;
}
static void ioprio_free_cpd(struct blkcg_policy_data *cpd)
{
struct ioprio_blkcg *blkcg = container_of(cpd, typeof(*blkcg), cpd);
kfree(blkcg);
}
static struct cftype ioprio_files[] = {
{
.name = "prio.class" ,
.seq_show = ioprio_show_prio_policy,
.write = ioprio_set_prio_policy,
},
{ } /* sentinel */
};
static struct blkcg_policy ioprio_policy = {
.dfl_cftypes = ioprio_files,
.legacy_cftypes = ioprio_files,
.cpd_alloc_fn = ioprio_alloc_cpd,
.cpd_free_fn = ioprio_free_cpd,
};
void blkcg_set_ioprio(struct bio *bio)
{
struct ioprio_blkcg *blkcg = blkcg_to_ioprio_blkcg(bio->bi_blkg->blkcg);
u16 prio;
if (!blkcg || blkcg->prio_policy == POLICY_NO_CHANGE)
return ;
if (blkcg->prio_policy == POLICY_PROMOTE_TO_RT ||
blkcg->prio_policy == POLICY_NONE_TO_RT) {
/*
* For RT threads , the default priority level is 4 because
* task_nice is 0 . By promoting non - RT io - priority to RT - class
* and default level 4 , those requests that are already
* RT - class but need a higher io - priority can use ioprio_set ( )
* to achieve this .
*/
if (IOPRIO_PRIO_CLASS(bio->bi_ioprio) != IOPRIO_CLASS_RT)
bio->bi_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_RT, 4 );
return ;
}
/*
* Except for IOPRIO_CLASS_NONE , higher I / O priority numbers
* correspond to a lower priority . Hence , the max_t ( ) below selects
* the lower priority of bi_ioprio and the cgroup I / O priority class .
* If the bio I / O priority equals IOPRIO_CLASS_NONE , the cgroup I / O
* priority is assigned to the bio .
*/
prio = max_t(u16, bio->bi_ioprio,
IOPRIO_PRIO_VALUE(blkcg->prio_policy, 0 ));
if (prio > bio->bi_ioprio)
bio->bi_ioprio = prio;
}
static int __init ioprio_init(void )
{
return blkcg_policy_register(&ioprio_policy);
}
static void __exit ioprio_exit(void )
{
blkcg_policy_unregister(&ioprio_policy);
}
module_init(ioprio_init);
module_exit(ioprio_exit);
Messung V0.5 in Prozent C=96 H=100 G=97
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland