rt-tests / cyclictest: Make cyclictest fail if it cannot run with requested priority.

Currently if a non-root user requests a priority higher than the soft limit in
/etc/security/limits.conf
the call to sched_setscheduler will silently fail and the user will be running
with priority of 0. Cyclictest will not complain, and display the
requested priority resulting in seemingly poor results.

The following patch fixes this by doing two things.

1. If the requested priority is higher than the soft limit but lower than the
hard limit, it will raise the soft limit to the requested priority.

2. If the requested priority is higher than the hard limit, it will fail with a
warning.

The patch should not affect privileged users.

Reported-by: Nicholas Mc Guire <der.herr@hofr.at>
Signed-off-by: John Kacur <jkacur@redhat.com>
Signed-off-by: Clark Williams <williams@redhat.com>
This commit is contained in:
John Kacur 2012-05-09 16:03:03 +02:00 committed by Clark Williams
parent 683a326a12
commit 81c42e0162
1 changed files with 75 additions and 1 deletions

View File

@ -31,6 +31,7 @@
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include "rt_numa.h"
@ -588,6 +589,79 @@ parse_time_string(char *val)
return t;
}
/*
* Raise the soft priority limit up to prio, if that is less than or equal
* to the hard limit
* if a call fails, return the error
* if successful return 0
* if fails, return -1
*/
static int raise_soft_prio(int policy, const struct sched_param *param)
{
int err;
int policy_max; /* max for scheduling policy such as SCHED_FIFO */
int soft_max;
int hard_max;
int prio;
struct rlimit rlim;
prio = param->sched_priority;
policy_max = sched_get_priority_max(policy);
if (policy_max == -1) {
err = errno;
err_msg("WARN: no such policy\n");
return err;
}
err = getrlimit(RLIMIT_RTPRIO, &rlim);
if (err) {
err = errno;
err_msg_n(err, "WARN: getrlimit failed\n");
return err;
}
soft_max = (rlim.rlim_cur == RLIM_INFINITY) ? policy_max : rlim.rlim_cur;
hard_max = (rlim.rlim_max == RLIM_INFINITY) ? policy_max : rlim.rlim_max;
if (prio > soft_max && prio <= hard_max) {
rlim.rlim_cur = prio;
err = setrlimit(RLIMIT_RTPRIO, &rlim);
if (err) {
err = errno;
err_msg_n(err, "WARN: setrlimit failed\n");
/* return err; */
}
} else {
err = -1;
}
return err;
}
/*
* Check the error status of sched_setscheduler
* If an error can be corrected by raising the soft limit priority to
* a priority less than or equal to the hard limit, then do so.
*/
static int setscheduler(pid_t pid, int policy, const struct sched_param *param)
{
int err = 0;
try_again:
err = sched_setscheduler(pid, policy, param);
if (err) {
err = errno;
if (err == EPERM) {
int err1;
err1 = raise_soft_prio(policy, param);
if (!err1) goto try_again;
}
}
return err;
}
/*
* timer thread
*
@ -646,7 +720,7 @@ void *timerthread(void *param)
memset(&schedp, 0, sizeof(schedp));
schedp.sched_priority = par->prio;
if (sched_setscheduler(0, par->policy, &schedp))
if (setscheduler(0, par->policy, &schedp))
fatal("timerthread%d: failed to set priority to %d\n", par->cpu, par->prio);
/* Get current time */