Fix a bug when calculating ticks_per_usec

I've noticed a wrong behavior when setting up some delays in a netem
qdisc.  I will try to make the things easier for the reader describing
the calls path.

To set up a delay (or jitter...) I use 'rtnl_netem_set_delay' which
requires an int parameter that tells the delay in micro seconds. Inside
this func, the delay is set up with the help of 'nl_us2ticks', which is
just an arithmetic operation (us * ticks_per_usec), where us is the
input parameter and ticks_per_usec is a global variable initialized in
'get_psched_settings'. And here is the problem:

If this variable is going to be calculated using '/proc/net/psched', I
think the file scan is not done properly.

I don't understand what the meaning of the asterisk is here:

int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom);
if (4 == r && nom == 1000000 && !got_tick)
        ticks_per_usec = (double)tick/(double)us;

The execution path never gets in the if statement, because r is always
3, and if the fourth parameter is read (avoiding the asterisk), there is
no variable to store it in, so it comes a segv. In my opinion we can get
rid of the if statement, because I think the proc psched file has always
a fixed format of 4 parameters, and 'nom' is always 1000000
(http://lxr.linux.no/#linux+v2.6.32/net/sched/sch_api.c#L1678).

Find attached a patch I did, if I am correct.
This commit is contained in:
Jose Ignacio Naranjo Hernández 2010-01-14 18:10:10 +01:00 committed by Thomas Graf
parent cafdaa4e06
commit 52d6b8b9ee

View file

@ -285,7 +285,7 @@ static void __init get_psched_settings(void)
{
char name[FILENAME_MAX];
FILE *fd;
int got_hz = 0, got_tick = 0;
int got_hz = 0;
if (getenv("HZ")) {
long hz = strtol(getenv("HZ"), NULL, 0);
@ -301,28 +301,25 @@ static void __init get_psched_settings(void)
if (getenv("TICKS_PER_USEC")) {
double t = strtod(getenv("TICKS_PER_USEC"), NULL);
ticks_per_usec = t;
got_tick = 1;
}
else {
if (getenv("PROC_NET_PSCHED"))
snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
else if (getenv("PROC_ROOT"))
snprintf(name, sizeof(name), "%s/net/psched",
getenv("PROC_ROOT"));
else
strncpy(name, "/proc/net/psched", sizeof(name) - 1);
if (getenv("PROC_NET_PSCHED"))
snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED"));
else if (getenv("PROC_ROOT"))
snprintf(name, sizeof(name), "%s/net/psched",
getenv("PROC_ROOT"));
else
strncpy(name, "/proc/net/psched", sizeof(name) - 1);
if ((fd = fopen(name, "r"))) {
uint32_t tick, us, nom;
int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom);
if (4 == r && nom == 1000000 && !got_tick)
if ((fd = fopen(name, "r"))) {
uint32_t tick, us;
/* the file contains 4 hexadecimals, but we just use
the first two of them */
int r = fscanf(fd, "%08x %08x", &tick, &us);
ticks_per_usec = (double)tick/(double)us;
fclose(fd);
fclose(fd);
}
}
}