On 08-May 21:21, Peter Zijlstra wrote:
> On Tue, Apr 02, 2019 at 11:41:41AM +0100, Patrick Bellasi wrote:
> > diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
> > index 22627f80063e..075c610adf45 100644
> > --- a/include/uapi/linux/sched.h
> > +++ b/include/uapi/linux/sched.h
> > @@ -40,6 +40,8 @@
> >  /* SCHED_ISO: reserved but not implemented yet */
> >  #define SCHED_IDLE         5
> >  #define SCHED_DEADLINE             6
> > +/* Must be the last entry: used to sanity check attr.policy values */
> > +#define SCHED_POLICY_MAX   SCHED_DEADLINE
> 
> This is a wee bit sad to put in a uapi header; but yeah, where else :/
> 
> Another option would be something like:
> 
> enum {
>       SCHED_NORMAL = 0,
>       SCHED_FIFO = 1,
>       SCHED_RR = 2,
>       SCHED_BATCH = 3,
>       /* SCHED_ISO = 4, reserved */
>       SCHED_IDLE = 5,
>       SCHED_DEADLINE = 6,
>       SCHED_POLICY_NR
> };
> 
> >  /* Can be ORed in to make sure the process is reverted back to 
> > SCHED_NORMAL on fork */
> >  #define SCHED_RESET_ON_FORK     0x40000000
> > @@ -50,9 +52,11 @@
> >  #define SCHED_FLAG_RESET_ON_FORK   0x01
> >  #define SCHED_FLAG_RECLAIM         0x02
> >  #define SCHED_FLAG_DL_OVERRUN              0x04
> > +#define SCHED_FLAG_KEEP_POLICY             0x08
> >  
> >  #define SCHED_FLAG_ALL     (SCHED_FLAG_RESET_ON_FORK       | \
> >                      SCHED_FLAG_RECLAIM             | \
> > -                    SCHED_FLAG_DL_OVERRUN)
> > +                    SCHED_FLAG_DL_OVERRUN          | \
> > +                    SCHED_FLAG_KEEP_POLICY)
> >  
> >  #endif /* _UAPI_LINUX_SCHED_H */
> > diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> > index d368ac26b8aa..20efb32e1a7e 100644
> > --- a/kernel/sched/core.c
> > +++ b/kernel/sched/core.c
> > @@ -4907,8 +4907,17 @@ SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct 
> > sched_attr __user *, uattr,
> >     if (retval)
> >             return retval;
> >  
> > -   if ((int)attr.sched_policy < 0)
> > +   /*
> > +    * A valid policy is always required from userspace, unless
> > +    * SCHED_FLAG_KEEP_POLICY is set and the current policy
> > +    * is enforced for this call.
> > +    */
> > +   if (attr.sched_policy > SCHED_POLICY_MAX &&
> > +       !(attr.sched_flags & SCHED_FLAG_KEEP_POLICY)) {
> >             return -EINVAL;
> > +   }
> 
> And given I just looked at those darn SCHED_* things, I now note the
> above does 'funny' things when passed: attr.policy=4.

Looking better at the code, I see now that we don't really need that
check anymore. Indeed, v8 introduced the support to change policy
specific and independent attributes at the same time. Thus:

1. the policy validity is already checked in:

     sched_setattr()
       sched_setattr()
         __sched_setscheduler()
            valid_policy()

   which knows how to deal with attr.policy=4 (i.e. -EINVAL)

2. when we pass in SCHED_FLAG_KEEP_POLICY we force the current policy
   by setting attr.sched_policy = SETPARAM_POLICY, so we just need a
   non negative policy being defined (usually 0 by default).

Thus, I'll remove the new #define and update the check above to be just:

        if (attr.sched_flags & SCHED_FLAG_KEEP_POLICY)
                attr.sched_policy = SETPARAM_POLICY;
        else if ((int)attr.sched_policy < 0)
                return -EINVAL;

which should cover the additional case:

   you can syscall with just SCHED_FLAG_KEEP_POLICY set if you want to
   change only cross-policy attributes.

> > +   if (attr.sched_flags & SCHED_FLAG_KEEP_POLICY)
> > +           attr.sched_policy = SETPARAM_POLICY;
> >  
> >     rcu_read_lock();
> >     retval = -ESRCH;

-- 
#include <best/regards.h>

Patrick Bellasi

Reply via email to