svn commit: r236441 - head/lib/libc/sys
Bruce Evans
brde at optusnet.com.au
Sat Jun 2 13:05:12 UTC 2012
On Sat, 2 Jun 2012, Ed Schouten wrote:
> Log:
> Remove invalid remark about pipes.
>
> The stat structures returned on pipes seems to contain all the
> information required by POSIX. Especially the wording "and thus to a
> pipe" makes little sense, because it seems to imply a certain
> relationship between sockets and pipes that simply isn't there.
It is because pipes are implemented in sockets in BSD. FreeBSD changed
this in 1996, but fstat(1) still claims it, and I got fstat(1) instead
of fstat(2) when I first tried to look this up:
% FSTAT(1) FreeBSD General Commands Manual FSTAT(1)
% ...
% For example, the addresses mentioned above are the addresses which the
% ``netstat -A'' command would print for tcp, udp, and unixdomain. Note
% that since pipes are implemented using sockets, a pipe appears as a con-
% nected unix domain stream socket. A unidirectional unix domain socket
% indicates the direction of flow with an arrow (``<-'' or ``->''), and a
% full duplex socket shows a double arrow (``<->'').
> Modified: head/lib/libc/sys/stat.2
> ==============================================================================
> --- head/lib/libc/sys/stat.2 Sat Jun 2 10:14:55 2012 (r236440)
> +++ head/lib/libc/sys/stat.2 Sat Jun 2 10:50:25 2012 (r236441)
> ...
> @@ -431,7 +431,7 @@ system call appeared in
> .Sh BUGS
> Applying
> .Fn fstat
> -to a socket (and thus to a pipe)
> +to a socket
> returns a zeroed buffer,
> except for the blocksize field,
> and a unique device and inode number.
This is still hard to parse. I think it says that fstat(2) returns a
zeroed buffer except for a nonzero blocksize field in it, and it returns
a unique device and inode number in addition to the buffer, but this
makes no sense since fstat(1) only returns one thing. This thing isn't
a generic buffer either -- other parts of the man page never use "buffer",
and mostly refer to the returned thing formally as "the struct pointed to
by sb". The normal informal description is more like "the stat buffer".
stat.2 seems to be wrong about the unique device number too.
uipc_usrreq.c sets st_blksize and st_ino as documented for the
"blocksize" and "inode number" (except st_ino can be non-unique after
wraparound at 2**32), but it always sets st_dev to the non-unique value
NODEV. Other subsystems are more careful about inventing unique
(st_dev, st_ino) ids. Pipes (ab)use devfs_alloc_cdp_inode() for st_dev
and alloc_unr() for st_ino. Sockets still use the primitive ++unp_ino
except when this wraps to 0, it is incremented again. I prefer the
primitive version. 2**32 inode numbers should be enough for anyone :-),
and there is no problem letting them grow very large and sparse, unlike
for pids and device numbers, so hashing them to give uniqueness is just
a waste of time and space. It probably takes a day or two to create
4G of sockets even if you try, and then the chance of a collision is about
1 in 2**32 unless you try.
POSIX requires most fields in struct stat including st_dev to be
"meaninful" for all POSIX file types including sockets, so the
non-unique st_dev is just another thing for this BUGS section.
This bug suite was only recently fixed for pipes. It seems to be
very easy to fix for st_dev of sockets -- just use a single id
reserved for all sockets. NODEV might already work, but only if
no other subsystem abuses it and it can't happen in normal use.
Or reserve a range of say 2**16 device ids for sockets, and use
this to make (st_dev, st_ino) pairs unique for sockets. Nothing
requires st_dev to be the same for all sockets, and 2**48 numbers
should really be enough for anyone.
Bruce
More information about the svn-src-all
mailing list