On Fri, 9 Dec 2005, Paul H. Hargrove wrote:

If one looks though enough kernel versions,

In the meantime, I've gotten a copy of kernel/sched.c from a SGI Prism kernel - I assume that it is the same used on Altix; this one has in the Makefile EXTRAVERSION = -sgi306rp31. So again, all prototypes of the sys_sched_setaffinity function that I've seen so far have 3 args... which means that no compiler tricks are needed to keep 3 different copies of the function.

one finds that some of them differ in what they will accept for the len.

OK, so this is a different problem...

Some produce EINVAL if len!=sizeof(long),

I beg to disagree. All the codes that I looked at test for

len < sizeof(new_mask)

and copy user data based on the size of new_mask, so if "len" is larger than sizeof(new_mask), no error occurs.

others (especially Altix) produce EINVAL if len is too short to cover all the machine's CPUs.

...so IMHO this test should be used instead to separate a long from a (larger) cpumask_t.

In the message that described your implementation you also wrote:

while on other kernels I find that a too-short mask is padded w/ zeros and no error results. So, we want a big value for len

Indeed some (more recent) kernels pad with zeros if "len" is too short. But a "big value for len" is again wrong.

I can see 4 cases, again by looking at the kernel code and not dealing with 2 vs. 3 args:

1. tests for len < sizeof(long) and copies only sizeof(len) if larger (backported 2.4 in RHEL3); this can be identified by passing "len" smaller than sizeof(long) which returns -EINVAL and then passing "len" of (or larger than) sizeof(long) which should not return error.

2. tests for len < sizeof(cpumask_t) and copies only sizeof(len) if larger (backported 2.4 from SGI, 2.6.3 from Mandrake 10.0); this can be identified by passing "len" shorter than sizeof(cpumask_t) which returns -EINVAL and then passing "len" of (or larger than) sizeof(cpu_size_t) which should not return error.

3. tests for len < sizeof(cpumask_t) and pads with zeros if true, otherwise copies only sizeof(cpumask_t) (2.6.9 in RHEL4 and 2.6.14). This can't really be identified as it doesn't return -EINVAL in any situation.

As you can see your suggestion to set "big value for len" would successfully pass _all_ of the above conditions and would therefore not offer any separation between the cases.

The stuff above applies to the _set function; the _get function is a bit different:

1. tests for len < sizeof(long) and returns -EINVAL if true. (backported 2.4 in RHEL3). This can be identified by passing "len" smaller than sizeof(long) which returns -EINVAL and then passing "len" of (or larger than) sizeof(long) which should not return error.

2. tests for len < sizeof(cpumask_t) and returns -EINVAL if true. (backported 2.4 from SGI, 2.6.3 from Mandraks 10.0, 2.6.9 from RHEL4, 2.6.14). This can be identified by passing "len" smaller than sizeof(cpumask_t) which returns -EINVAL and then passing "len" of (or larger than) sizeof(cpumask_t) which should not return error.

Case 1. of _set is associated to case 1. of _get.
Cases 2. and 3. of _set are both associated to case 2. of _get.

So IMHO the test should be made with the _get function (as explained in a previous message), by setting len=sizeof(long) which would allow the case 1. to work fine, while case 2. would return -EINVAL, exactly opposite from the code that you proposed.

--
Bogdan Costescu

IWR - Interdisziplinaeres Zentrum fuer Wissenschaftliches Rechnen
Universitaet Heidelberg, INF 368, D-69120 Heidelberg, GERMANY
Telephone: +49 6221 54 8869, Telefax: +49 6221 54 8868
E-mail: bogdan.coste...@iwr.uni-heidelberg.de

Reply via email to