Re: [PATCH v4 7/7] sched/fair: Fair server interface

From: Peter Zijlstra
Date: Tue Sep 05 2023 - 12:44:52 EST


On Thu, Aug 31, 2023 at 10:28:58PM +0200, Daniel Bristot de Oliveira wrote:
> +static ssize_t
> +sched_fair_server_runtime_write(struct file *filp, const char __user *ubuf,
> + size_t cnt, loff_t *ppos)
> +{
> + long cpu = (long) ((struct seq_file *) filp->private_data)->private;
> + struct rq *rq = cpu_rq(cpu);
> + unsigned long flags;
> + u64 runtime;
> + int err;
> +
> + err = kstrtoull_from_user(ubuf, cnt, 10, &runtime);
> + if (err)
> + return err;
> +
> + raw_spin_rq_lock_irqsave(rq, flags);
> + if (runtime > rq->fair_server.dl_period)
> + err = -EINVAL;
> + else
> + rq->fair_server.dl_runtime = runtime;
> + raw_spin_rq_unlock_irqrestore(rq, flags);
> +
> + if (err)
> + return err;
> +
> + *ppos += cnt;
> + return cnt;
> +}

> +static ssize_t
> +sched_fair_server_period_write(struct file *filp, const char __user *ubuf,
> + size_t cnt, loff_t *ppos)
> +{
> + long cpu = (long) ((struct seq_file *) filp->private_data)->private;
> + struct rq *rq = cpu_rq(cpu);
> + unsigned long flags;
> + u64 period;
> + int err;
> +
> + err = kstrtoull_from_user(ubuf, cnt, 10, &period);
> + if (err)
> + return err;
> +
> + if (period < fair_server_period_min || period > fair_server_period_max)
> + return -EINVAL;
> +
> + raw_spin_rq_lock_irqsave(rq, flags);
> + if (period < rq->fair_server.dl_runtime)
> + err = -EINVAL;
> + else
> + rq->fair_server.dl_period = period;
> + raw_spin_rq_unlock_irqrestore(rq, flags);
> +
> + if (err)
> + return err;
> +
> + *ppos += cnt;
> + return cnt;
> +}

> +static ssize_t
> +sched_fair_server_defer_write(struct file *filp, const char __user *ubuf,
> + size_t cnt, loff_t *ppos)
> +{
> + long cpu = (long) ((struct seq_file *) filp->private_data)->private;
> + struct rq *rq = cpu_rq(cpu);
> + unsigned long flags;
> + u64 defer;
> + int err;
> +
> + err = kstrtoull_from_user(ubuf, cnt, 10, &defer);
> + if (err)
> + return err;
> +
> + if (defer < 0 || defer > 1)
> + return -EINVAL;
> +
> + raw_spin_rq_lock_irqsave(rq, flags);
> + rq->fair_server_defer = defer;
> + raw_spin_rq_unlock_irqrestore(rq, flags);
> +
> + *ppos += cnt;
> + return cnt;
> +}

Surely we can write a single function that does all of that with less
duplication?

Additionally, should not the deadline parameters be vetted by access
control before being accepted ?

Perhaps something like so:

static ssize_t
sched_fair_server_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos, enum dl_param param)
{
long cpu = (long) ((struct seq_file *) filp->private_data)->private;
struct rq *rq = cpu_rq(cpu);
u64 value;

err = kstrtoull_from_user(ubuf, cnt, 10, &value);
if (err)
return err;

scoped_guard (rq_lock_irqsave, rq) {

u64 runtime, deadline, period;

runtime = rq->fair_server.dl_runtime;
deadline = rq->fair_server.dl_deadline;
period = rq->fair_server.dl_period;

switch (param) {
case dl_runtime: runtime = value; break;
case dl_deadline: deadline = value; break;
case dl_period: period = value; break;
}

if (runtime > deadline ||
deadline > period ||
/* more stuff like access controll */)
return -EINVAL;

rq->fair_server.dl_runtime = runtime;
rq->fair_server.dl_deadline = deadline;
rq->fair_server.dl_period = period;
}

*ppos += cnt;
return cnt;
}