newnfs client and statfs

Bruce Evans brde at optusnet.com.au
Sun May 1 16:23:55 UTC 2011


On Sun, 1 May 2011, Jeremy Chadwick wrote:

> [snip]
> On Sun, May 01, 2011 at 10:37:18AM -0400, Rick Macklem wrote:
>>> % + sbp->f_ffree = (sfp->sf_ffiles & OFF_MAX);
>>>
>>> Any masking here is logically wrong, and in practice just destroys the
>>> sign bit, as described above for the 0x7fffffff mask with old 32 bit

This got a bit tangled.  I will reply more to the older reply.

>> - except there isn't a UINT64_MAX, INT64_MAX defined in sys/*.h as
>>   far as I can see. How do I express these constants? Do I have to
>>   convert 0x7ffffffffffffff to decimal and use that?

UINT64_MAX, etc., are defined in <sys/stdint.h>, which doesn't even need
to be included explicitly, since it is (bogusly) standard namespace
pollution in <sys/systm.h>.  This namespace pollution gives the bizarre
situation that you have to include <sys/limits.h> to get the limits for
basic types, but you get the limits for the fix-with types whether you
want them or not, except in rare cases where <sys/systm.h> is not needed
for other reasons.

> Aren't these effectively defined in <sys/limits.h> as UQUAD_MAX and
> QUAD_MAX?  These get translated/pulled in from <machine/_limits.h>,
> which varies per architecture.  This looks like the translation based on
> looking at the respective include files per arch:

No.  UQUAD_MAX and QUAD_MAX are historical mistakes.  quad_t should be
4 times as large as a machine register, but for compatibility it must
be precisely 64 bits.  This makes it just an obfuscation in new code
(code newer than 199 when int64_t became Standard with C99).

> i386: UQUAD_MAX == __UQUAD_MAX == __ULLONG_MAX == 0xffffffffffffffffULL
> i386: QUAD_MAX  == __QUAD_MAX  == __LLONG_MAX  == 0x7fffffffffffffffLL
>
> amd64: UQUAD_MAX == __UQUAD_MAX == __ULONG_MAX  == 0xffffffffffffffffUL
> amd64: QUAD_MAX  == __QUAD_MAX  == __LONG_MAX   == 0x7fffffffffffffffL
>
> There are some #ifdef's in <sys/limits.h> around some of these
> declarations which I don't understand (like __BSD_VISIBLE), but I would
> imagine the above declarations would do what you want.

These are just ways of spelling 2**64-1 and 2**63-1.  For all fixed-with
types, macros for the limits aren't really needed, since they are
almost machine-dependent so you can almost write them as hex constants
even more easily than you can remember where their macros are defined.
But there are subleties for their types.  These are visible in the
above definitions.  On amd64, their basic types are unsigned long and
long, respectively, while on i386 their types are unsigned long long
and long long. respectively.  Also, type suffixes on the hex constants
may be necessary for technical and bogonial reasons.  Type suffixes
should not be needed for unsigned constants, but header files must use
them even then to prevent warnings from cc -std89 for literal constants
larger than ULONG_MAX (gcc warns about this because C90 doesn;t support
integer types larger than unsigned long).  Type suffixes are needed for
signed constants like QUAD_MAX to make the constant have a signed type
instead of the default of unsigned int (for constants larger than UINT_MAX).
Most code using the constants doesn't care about these subtleties, so it
can use its own literal constant.

Bruce


More information about the freebsd-fs mailing list