Skip to content

Commit 5bc34be

Browse files
htejunPeter Zijlstra
authored andcommitted
sched/core: Reorganize cgroup bandwidth control interface file writes
- Move input parameter validation from tg_set_cfs_bandwidth() to the new outer function tg_set_bandwidth(). The outer function handles parameters in usecs, validates them and calls tg_set_cfs_bandwidth() which converts them into nsecs. This matches tg_bandwidth() on the read side. - max/min_cfs_* consts are now used by tg_set_bandwidth(). Relocate, convert into usecs and drop "cfs" from the names. - Reimplement cpu_cfs_{period|quote|burst}_write_*() using tg_bandwidth() and tg_set_bandwidth() and replace "cfs" in the names with "bw". - Update cpu_max_write() to use tg_set_bandiwdth(). cpu_period_quota_parse() is updated to drop nsec conversion accordingly. This aligns the behavior with cfs_period_quota_print(). - Drop now unused tg_set_cfs_{period|quota|burst}(). - While at it, for consistency, rename default_cfs_period() to default_bw_period_us() and make it return usecs. This is to prepare for adding bandwidth control support to sched_ext. tg_set_bandwidth() will be used as the muxing point. No functional changes intended. Signed-off-by: Tejun Heo <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 43e33f5 commit 5bc34be

File tree

3 files changed

+106
-113
lines changed

3 files changed

+106
-113
lines changed

kernel/sched/core.c

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -9309,47 +9309,23 @@ static u64 cpu_shares_read_u64(struct cgroup_subsys_state *css,
93099309
#ifdef CONFIG_CFS_BANDWIDTH
93109310
static DEFINE_MUTEX(cfs_constraints_mutex);
93119311

9312-
const u64 max_cfs_quota_period = 1 * NSEC_PER_SEC; /* 1s */
9313-
static const u64 min_cfs_quota_period = 1 * NSEC_PER_MSEC; /* 1ms */
9314-
/* More than 203 days if BW_SHIFT equals 20. */
9315-
static const u64 max_cfs_runtime = MAX_BW * NSEC_PER_USEC;
9316-
93179312
static int __cfs_schedulable(struct task_group *tg, u64 period, u64 runtime);
93189313

9319-
static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota,
9320-
u64 burst)
9314+
static int tg_set_cfs_bandwidth(struct task_group *tg,
9315+
u64 period_us, u64 quota_us, u64 burst_us)
93219316
{
93229317
int i, ret = 0, runtime_enabled, runtime_was_enabled;
93239318
struct cfs_bandwidth *cfs_b = &tg->cfs_bandwidth;
9319+
u64 period, quota, burst;
93249320

9325-
if (tg == &root_task_group)
9326-
return -EINVAL;
9327-
9328-
/*
9329-
* Ensure we have at some amount of bandwidth every period. This is
9330-
* to prevent reaching a state of large arrears when throttled via
9331-
* entity_tick() resulting in prolonged exit starvation.
9332-
*/
9333-
if (quota < min_cfs_quota_period || period < min_cfs_quota_period)
9334-
return -EINVAL;
9321+
period = (u64)period_us * NSEC_PER_USEC;
93359322

9336-
/*
9337-
* Likewise, bound things on the other side by preventing insane quota
9338-
* periods. This also allows us to normalize in computing quota
9339-
* feasibility.
9340-
*/
9341-
if (period > max_cfs_quota_period)
9342-
return -EINVAL;
9343-
9344-
/*
9345-
* Bound quota to defend quota against overflow during bandwidth shift.
9346-
*/
9347-
if (quota != RUNTIME_INF && quota > max_cfs_runtime)
9348-
return -EINVAL;
9323+
if (quota_us == RUNTIME_INF)
9324+
quota = RUNTIME_INF;
9325+
else
9326+
quota = (u64)quota_us * NSEC_PER_USEC;
93499327

9350-
if (quota != RUNTIME_INF && (burst > quota ||
9351-
burst + quota > max_cfs_runtime))
9352-
return -EINVAL;
9328+
burst = (u64)burst_us * NSEC_PER_USEC;
93539329

93549330
/*
93559331
* Prevent race between setting of cfs_rq->runtime_enabled and
@@ -9437,50 +9413,6 @@ static u64 tg_get_cfs_burst(struct task_group *tg)
94379413
return burst_us;
94389414
}
94399415

9440-
static int tg_set_cfs_period(struct task_group *tg, long cfs_period_us)
9441-
{
9442-
u64 quota, period, burst;
9443-
9444-
if ((u64)cfs_period_us > U64_MAX / NSEC_PER_USEC)
9445-
return -EINVAL;
9446-
9447-
period = (u64)cfs_period_us * NSEC_PER_USEC;
9448-
quota = tg->cfs_bandwidth.quota;
9449-
burst = tg->cfs_bandwidth.burst;
9450-
9451-
return tg_set_cfs_bandwidth(tg, period, quota, burst);
9452-
}
9453-
9454-
static int tg_set_cfs_quota(struct task_group *tg, long cfs_quota_us)
9455-
{
9456-
u64 quota, period, burst;
9457-
9458-
period = ktime_to_ns(tg->cfs_bandwidth.period);
9459-
burst = tg->cfs_bandwidth.burst;
9460-
if (cfs_quota_us < 0)
9461-
quota = RUNTIME_INF;
9462-
else if ((u64)cfs_quota_us <= U64_MAX / NSEC_PER_USEC)
9463-
quota = (u64)cfs_quota_us * NSEC_PER_USEC;
9464-
else
9465-
return -EINVAL;
9466-
9467-
return tg_set_cfs_bandwidth(tg, period, quota, burst);
9468-
}
9469-
9470-
static int tg_set_cfs_burst(struct task_group *tg, long cfs_burst_us)
9471-
{
9472-
u64 quota, period, burst;
9473-
9474-
if ((u64)cfs_burst_us > U64_MAX / NSEC_PER_USEC)
9475-
return -EINVAL;
9476-
9477-
burst = (u64)cfs_burst_us * NSEC_PER_USEC;
9478-
period = ktime_to_ns(tg->cfs_bandwidth.period);
9479-
quota = tg->cfs_bandwidth.quota;
9480-
9481-
return tg_set_cfs_bandwidth(tg, period, quota, burst);
9482-
}
9483-
94849416
struct cfs_schedulable_data {
94859417
struct task_group *tg;
94869418
u64 period, quota;
@@ -9614,6 +9546,11 @@ static int cpu_cfs_local_stat_show(struct seq_file *sf, void *v)
96149546
return 0;
96159547
}
96169548

9549+
const u64 max_bw_quota_period_us = 1 * USEC_PER_SEC; /* 1s */
9550+
static const u64 min_bw_quota_period_us = 1 * USEC_PER_MSEC; /* 1ms */
9551+
/* More than 203 days if BW_SHIFT equals 20. */
9552+
static const u64 max_bw_runtime_us = MAX_BW;
9553+
96179554
static void tg_bandwidth(struct task_group *tg,
96189555
u64 *period_us_p, u64 *quota_us_p, u64 *burst_us_p)
96199556
{
@@ -9634,6 +9571,50 @@ static u64 cpu_period_read_u64(struct cgroup_subsys_state *css,
96349571
return period_us;
96359572
}
96369573

9574+
static int tg_set_bandwidth(struct task_group *tg,
9575+
u64 period_us, u64 quota_us, u64 burst_us)
9576+
{
9577+
const u64 max_usec = U64_MAX / NSEC_PER_USEC;
9578+
9579+
if (tg == &root_task_group)
9580+
return -EINVAL;
9581+
9582+
/* Values should survive translation to nsec */
9583+
if (period_us > max_usec ||
9584+
(quota_us != RUNTIME_INF && quota_us > max_usec) ||
9585+
burst_us > max_usec)
9586+
return -EINVAL;
9587+
9588+
/*
9589+
* Ensure we have some amount of bandwidth every period. This is to
9590+
* prevent reaching a state of large arrears when throttled via
9591+
* entity_tick() resulting in prolonged exit starvation.
9592+
*/
9593+
if (quota_us < min_bw_quota_period_us ||
9594+
period_us < min_bw_quota_period_us)
9595+
return -EINVAL;
9596+
9597+
/*
9598+
* Likewise, bound things on the other side by preventing insane quota
9599+
* periods. This also allows us to normalize in computing quota
9600+
* feasibility.
9601+
*/
9602+
if (period_us > max_bw_quota_period_us)
9603+
return -EINVAL;
9604+
9605+
/*
9606+
* Bound quota to defend quota against overflow during bandwidth shift.
9607+
*/
9608+
if (quota_us != RUNTIME_INF && quota_us > max_bw_runtime_us)
9609+
return -EINVAL;
9610+
9611+
if (quota_us != RUNTIME_INF && (burst_us > quota_us ||
9612+
burst_us + quota_us > max_bw_runtime_us))
9613+
return -EINVAL;
9614+
9615+
return tg_set_cfs_bandwidth(tg, period_us, quota_us, burst_us);
9616+
}
9617+
96379618
static s64 cpu_quota_read_s64(struct cgroup_subsys_state *css,
96389619
struct cftype *cft)
96399620
{
@@ -9652,22 +9633,37 @@ static u64 cpu_burst_read_u64(struct cgroup_subsys_state *css,
96529633
return burst_us;
96539634
}
96549635

9655-
static int cpu_cfs_period_write_u64(struct cgroup_subsys_state *css,
9656-
struct cftype *cftype, u64 cfs_period_us)
9636+
static int cpu_period_write_u64(struct cgroup_subsys_state *css,
9637+
struct cftype *cftype, u64 period_us)
96579638
{
9658-
return tg_set_cfs_period(css_tg(css), cfs_period_us);
9639+
struct task_group *tg = css_tg(css);
9640+
u64 quota_us, burst_us;
9641+
9642+
tg_bandwidth(tg, NULL, &quota_us, &burst_us);
9643+
return tg_set_bandwidth(tg, period_us, quota_us, burst_us);
96599644
}
96609645

9661-
static int cpu_cfs_quota_write_s64(struct cgroup_subsys_state *css,
9662-
struct cftype *cftype, s64 cfs_quota_us)
9646+
static int cpu_quota_write_s64(struct cgroup_subsys_state *css,
9647+
struct cftype *cftype, s64 quota_us)
96639648
{
9664-
return tg_set_cfs_quota(css_tg(css), cfs_quota_us);
9649+
struct task_group *tg = css_tg(css);
9650+
u64 period_us, burst_us;
9651+
9652+
if (quota_us < 0)
9653+
quota_us = RUNTIME_INF;
9654+
9655+
tg_bandwidth(tg, &period_us, NULL, &burst_us);
9656+
return tg_set_bandwidth(tg, period_us, quota_us, burst_us);
96659657
}
96669658

9667-
static int cpu_cfs_burst_write_u64(struct cgroup_subsys_state *css,
9668-
struct cftype *cftype, u64 cfs_burst_us)
9659+
static int cpu_burst_write_u64(struct cgroup_subsys_state *css,
9660+
struct cftype *cftype, u64 burst_us)
96699661
{
9670-
return tg_set_cfs_burst(css_tg(css), cfs_burst_us);
9662+
struct task_group *tg = css_tg(css);
9663+
u64 period_us, quota_us;
9664+
9665+
tg_bandwidth(tg, &period_us, &quota_us, NULL);
9666+
return tg_set_bandwidth(tg, period_us, quota_us, burst_us);
96719667
}
96729668
#endif /* CONFIG_CFS_BANDWIDTH */
96739669

@@ -9733,17 +9729,17 @@ static struct cftype cpu_legacy_files[] = {
97339729
{
97349730
.name = "cfs_period_us",
97359731
.read_u64 = cpu_period_read_u64,
9736-
.write_u64 = cpu_cfs_period_write_u64,
9732+
.write_u64 = cpu_period_write_u64,
97379733
},
97389734
{
97399735
.name = "cfs_quota_us",
97409736
.read_s64 = cpu_quota_read_s64,
9741-
.write_s64 = cpu_cfs_quota_write_s64,
9737+
.write_s64 = cpu_quota_write_s64,
97429738
},
97439739
{
97449740
.name = "cfs_burst_us",
97459741
.read_u64 = cpu_burst_read_u64,
9746-
.write_u64 = cpu_cfs_burst_write_u64,
9742+
.write_u64 = cpu_burst_write_u64,
97479743
},
97489744
{
97499745
.name = "stat",
@@ -9940,22 +9936,20 @@ static void __maybe_unused cpu_period_quota_print(struct seq_file *sf,
99409936
}
99419937

99429938
/* caller should put the current value in *@periodp before calling */
9943-
static int __maybe_unused cpu_period_quota_parse(char *buf,
9944-
u64 *periodp, u64 *quotap)
9939+
static int __maybe_unused cpu_period_quota_parse(char *buf, u64 *period_us_p,
9940+
u64 *quota_us_p)
99459941
{
99469942
char tok[21]; /* U64_MAX */
99479943

9948-
if (sscanf(buf, "%20s %llu", tok, periodp) < 1)
9944+
if (sscanf(buf, "%20s %llu", tok, period_us_p) < 1)
99499945
return -EINVAL;
99509946

9951-
*periodp *= NSEC_PER_USEC;
9952-
9953-
if (sscanf(tok, "%llu", quotap))
9954-
*quotap *= NSEC_PER_USEC;
9955-
else if (!strcmp(tok, "max"))
9956-
*quotap = RUNTIME_INF;
9957-
else
9958-
return -EINVAL;
9947+
if (sscanf(tok, "%llu", quota_us_p) < 1) {
9948+
if (!strcmp(tok, "max"))
9949+
*quota_us_p = RUNTIME_INF;
9950+
else
9951+
return -EINVAL;
9952+
}
99599953

99609954
return 0;
99619955
}
@@ -9975,14 +9969,13 @@ static ssize_t cpu_max_write(struct kernfs_open_file *of,
99759969
char *buf, size_t nbytes, loff_t off)
99769970
{
99779971
struct task_group *tg = css_tg(of_css(of));
9978-
u64 period = tg_get_cfs_period(tg);
9979-
u64 burst = tg->cfs_bandwidth.burst;
9980-
u64 quota;
9972+
u64 period_us, quota_us, burst_us;
99819973
int ret;
99829974

9983-
ret = cpu_period_quota_parse(buf, &period, &quota);
9975+
tg_bandwidth(tg, &period_us, NULL, &burst_us);
9976+
ret = cpu_period_quota_parse(buf, &period_us, &quota_us);
99849977
if (!ret)
9985-
ret = tg_set_cfs_bandwidth(tg, period, quota, burst);
9978+
ret = tg_set_bandwidth(tg, period_us, quota_us, burst_us);
99869979
return ret ?: nbytes;
99879980
}
99889981
#endif /* CONFIG_CFS_BANDWIDTH */
@@ -10019,7 +10012,7 @@ static struct cftype cpu_files[] = {
1001910012
.name = "max.burst",
1002010013
.flags = CFTYPE_NOT_ON_ROOT,
1002110014
.read_u64 = cpu_burst_read_u64,
10022-
.write_u64 = cpu_cfs_burst_write_u64,
10015+
.write_u64 = cpu_burst_write_u64,
1002310016
},
1002410017
#endif /* CONFIG_CFS_BANDWIDTH */
1002510018
#ifdef CONFIG_UCLAMP_TASK_GROUP

kernel/sched/fair.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6422,7 +6422,7 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer)
64226422
* to fail.
64236423
*/
64246424
new = old * 2;
6425-
if (new < max_cfs_quota_period) {
6425+
if (new < max_bw_quota_period_us * NSEC_PER_USEC) {
64266426
cfs_b->period = ns_to_ktime(new);
64276427
cfs_b->quota *= 2;
64286428
cfs_b->burst *= 2;
@@ -6456,7 +6456,7 @@ void init_cfs_bandwidth(struct cfs_bandwidth *cfs_b, struct cfs_bandwidth *paren
64566456
raw_spin_lock_init(&cfs_b->lock);
64576457
cfs_b->runtime = 0;
64586458
cfs_b->quota = RUNTIME_INF;
6459-
cfs_b->period = ns_to_ktime(default_cfs_period());
6459+
cfs_b->period = us_to_ktime(default_bw_period_us());
64606460
cfs_b->burst = 0;
64616461
cfs_b->hierarchical_quota = parent ? parent->hierarchical_quota : RUNTIME_INF;
64626462

kernel/sched/sched.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -403,15 +403,15 @@ static inline bool dl_server_active(struct sched_dl_entity *dl_se)
403403
extern struct list_head task_groups;
404404

405405
#ifdef CONFIG_CFS_BANDWIDTH
406-
extern const u64 max_cfs_quota_period;
406+
extern const u64 max_bw_quota_period_us;
407407

408408
/*
409-
* default period for cfs group bandwidth.
410-
* default: 0.1s, units: nanoseconds
409+
* default period for group bandwidth.
410+
* default: 0.1s, units: microseconds
411411
*/
412-
static inline u64 default_cfs_period(void)
412+
static inline u64 default_bw_period_us(void)
413413
{
414-
return 100000000ULL;
414+
return 100000ULL;
415415
}
416416
#endif /* CONFIG_CFS_BANDWIDTH */
417417

0 commit comments

Comments
 (0)