Subject: Re: is __NetBSD_Version__ being misused (again) ?
To: Pavel Cahyna <pavel@NetBSD.org>
From: Robert Elz <kre@munnari.OZ.AU>
List: tech-kern
Date: 11/17/2007 23:13:41
Before I start, as an aside, every time I look at __NetBSD_Version__
and the way it should be used with __NetBSD_Prereq__() it takes me
ages of staring at the macro, and imagining how it should be correctly
used, before it (once again) dawns on me just how it is planned to
work...

Please, someone, consider this a request for a NetBSD_Version.9 man
page (or perhaps an lkm.9 man page or something) which documents this
fairly important part of the kernel infrastructure (and which also should
avoid misunderstandings about what the definition is really for).

Now, back to the actual issue...

    Date:        Sat, 17 Nov 2007 12:03:14 +0100
    From:        Pavel Cahyna <pavel@NetBSD.org>
    Message-ID:  <20071117110314.GA401@beta.martani.repy.net>

  | As the release is approaching, it would be good to solve this problem if
  | there is any.

Yes...   I had been wondering if anyone was even considering it.  Thanks
for bringing it back from limbo!

Until now, the only response to my message had been an explanation of
why NetBSD_Version needed to be bumped - which was interesting information
(I'm still > a year behind in my list reading, so I'm not up to date
on what's happening) but not really relevant - I never doubted but that
there was a good reason for the bumps, the issue is the actual value
chosen.

  | But I must admit I don't see it. __NetBSD_Prereq__ is defined as:
  | 
  | #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
  |     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
  | 
  | so __NetBSD_Prereq__(4,0,0) will succeed if __NetBSD_Version__ is
  | 400000003. 

Yes, but I don't think that's quite the point, the intention isn't
to be able to say "at least NetBSD version N" - that's a useless
test for things like LKM's which (even though I think we shouldn't
have them at all...) is where this macro is intended to be used
(that's what __NetBSD_Version__ is for after all).   For that, an
LKM knows (or should know) the state of the kernel for every version up
to the version that exists when it is built - that's all just
historical information, it cannot possibly know what kernel
interface changes might exist in versions that follow the last one
it knows about.

So, what is important is that the LKM has a way of asking "is the
current version of NetBSD newer than the one I know about".

So, assuming I'm building an LKM for 4.0 today, how do I use the
macro so the code will compile on 4.0, and nothing after it?

Obviously, not all LKMs will want to support everything back to 0.8
(or whatever it was that was first released), so they also need a way
to test a base version, and not work for any NetBSD earlier than
that one.

The __NetBSD_Prereq__() macro is (I believe) intended to fill both
of those purposes (and if it does, it also can obviously handle the
case of compiling different code for different NetBSD versions, so the
same LKM source file can be comp[iled for 2.0 3.0 3.1 4.0 ...).

In order to do that, the macro needs to be able to separate each
individual NetBSD version, that is, there needs to be a way to use
it that will succeed on exactly version X, and nothing else (using
the macro more than once with different parameters is clearly OK).

I don't believe that can be done with __NetBSD_Version__ set to
400000003 in NetBSD 4.0 - there would be no way for any use of the
macro to tell the difference between 4.0 and 4.0.1.

If you can show me how to manage it, please do.

  | Also, given that there are probably exactly 0 uses of __NetBSD_Prereq__ in
  | the world (google code search reveals no uses outside the file where it is
  | defined)

That's an interesting point, but actually makes the problem worse I
believe (harder to be confident that things are being done properly).

For the __NetBSD_Prereq__() macro, if nothing anywhwre uses it (and
that's certainly possible, though I'm not sure that proprietry LKMs
will necessarily be found by google) then the macro might perhaps
simply be deleted.

But the macro isn't the issue, it is  the definition of __NetBSD_Version__
which currently (in 4.0_RCn, not other versions that I'm aware of)
isn't defined in accordance with its specification a few lines higher
up param.h.  That is:

/* 
 *      #define __NetBSD_Version__ MMmmrrpp00
 *								(etc)

with the last two decimal digits always 0.

If we're assuming that __NetBSD_Prereq__() isn't the way it is tested,
then it is probably necessary to check every use of __NetBSD_Version__
(in NetBSD code and every LKM everywhere) to see if any of those uses
might fail with __NetBSD_Version__ having its non-standard value in
4.0 (assuming it remains as it is when 4.0 is released).

  | and that the test was wrong for a long time before anybody
  | noticed, I don't think issues with it are especially important.

It isn't the test, the test is fine, the problem is with the definition
of __NetBSD_Version__ - and any problems with it won't appear until
NetBSD 4.0.1 is released.   The problem is that __NetBSD_Prereq__() cannot
possibly distinguish between 4.0 (the way __NetBSD_Version__ for it
seems to be going to be defined) and 4.0.1.

That's why I'm suggesting that 4.0 be stillborn, and the exact same
code (other than the definition of __NetBSD_Version__ obviously) be
released as 4.1 instead (it could be 4.0.1 but I think that would be
a little peculiar).

kre

ps: if anyone ever actually makes a decision on what to do about this,
then please note that PR 36918 is open on this issue, it should be
dealt with at the same time (it was filed against 4.0 RC1 but nothing
relevant has altered in the later RCs I believe).