test hash functions for fsid

Bruce Evans brde at optusnet.com.au
Wed May 8 18:13:25 UTC 2019

On Wed, 8 May 2019, Conrad Meyer wrote:

Another reply.

> (A) FSIDs themselves have poor initial distribution and *very* few
> unique bits (i.e., for filesystems that use vfs_getnewfsid, the int32
> fsid val[1] will be identical across all filesystems of the same type,
> such as NFS mounts).  The remaining val[0] is unique due to an
> incrementing global counter.  You could pretty easily extract the
> vfs_getnewfsid() code out to userspace to simulate creating a bunch of
> fsid_t's and run some tests on that list.

It is a bug to actually use val[1] or 64-bit dev_t.  Using it is either
unnecessary because val[0] is unique, or breaks compat syscalls.  See
my previous reply.  (I have a patch to make the compat syscalls fail
if they would truncate the dev_t, but it is too strict to be the default
and I forget if I committed it).

> It isn't a real world
> distribution but it would probably be pretty close, outside of ZFS.
> ZFS FSIDs have 8 bits of shared vfs type, but the remaining 56 bits
> appears to be generated by arc4rand(9), so ZFS FSIDs will have good
> distribution even without hashing.

Bug in zfs.

Even stat(1) doesn't understand these 64-bit numbers.  It misformats
them in decimal:

$ stat ~
16921688315829575803 2179998 drwxr-xr-x 62 bde bde 18446744073709551615 85 "Nov 25 21:21:07 2016" "May  8 16:33:55 2019" "May  8 16:33:55 2019" "Sep 28 00:06:41 2015" 5632 24 0x800 /home/bde

The first large number is st_dev and the second large number is st_rdev.
The decimal formatting of these is hard enough to read when they are
32 bits.  The 1844 number looks a like it is near UINT64_MAX, and is
in fact exactly that, so it is far from unique.  It is apparently just
NODEV = (dev_t)(-1).  This is correct except for the formatting, while
in ffs st_rdev is garbage except for actual devices, since ufs_getattr()
sets va_rdev to di_rdev even for non-devices, but for non-devices
di_rdev is an alias for the first block number.

I did commit my checks for truncation of dev_t's (r335035 and r335053).
Fixing makedev() put the synthetic major number 255 in vfs_getnewfsid()
back in the low 32 bits, so the checks usually pass for nfs.  However,
for zfs, they would often fail for the large number in st_dev, and always
fail for regular files for the large number NODEV = UINT64_MAX in st_rdev.
They should fail for NODEV for regular files on all file systems.


More information about the freebsd-fs mailing list