Date: Mon, 14 Feb 2011 18:44:55 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Garrett Cooper <yanegomi@gmail.com> Cc: freebsd-fs@FreeBSD.org Subject: Re: The history behind the undocumented NetBSD stat syscalls? Message-ID: <20110214182441.X1003@besplex.bde.org> In-Reply-To: <AANLkTiniX4xe8ri2CYFn34AMyeC4m0eR4WJv8-b4SXkN@mail.gmail.com> References: <AANLkTiniX4xe8ri2CYFn34AMyeC4m0eR4WJv8-b4SXkN@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 13 Feb 2011, Garrett Cooper wrote: > I was poking through vfs_syscalls.c and I noticed that there was a > syscall called nlstat, and nstat, and a kernel-public only helper > function called cvtnstat: > These aren't used anywhere in our source tree (I trimmed out the > false positives -- i.e. connstat and instat), minus their declarations > in kern/vfs_syscalls.c, etc: I think these are the "new" stat() syscalls in 4.4BSD. Ones using struct ostat are normal "old" stat calls. But normality is reversed in FreeBSD. FreeBSD was forced to make a clean break with FreeBSD-1, and from FreeBSD-2 on it didn't have the the "old" stat calls. Until someone made a mess by importing anachronous bits from NetBSD. Both nstat() and ostat() might be useful for binary compatibilty with NetBSD, but I think there are too many other differences for actual usefulness. NetBSD in 2005 has even more "old" stat structs and corresponding syscalls. They are named a little differently: o struct stat43, for 4.3BSD (Net/2, 386BSD, FreeBSD-1?). This is under a _KERNEL ifdef as it should be. This lets the kernel support it but prevents current sources from using it. The corresponding ifdef in FreeBSD is wrong -- it is __BSD_VISIBLE. So we have the silly situation that FreeBSD makes visible old NetBSD interfaces that NetBSD doesn't make visible. FreeBSD does better with its own "old" structs, e.g., struct ostatfs. struct stat43 seems to be compatible with struct ostat. These are really old. They have 16-bit uids and gids, which are correctly implemented by spelling their types as __uint16_t (except in NetBSD there is namespace pollution by spelling this as u_int16_t). Some of the other fields are not so carefully handled (using non-fixed-width typedefs which are not binary compatible with the future), so it is hard to see if their types are actually the same: - st_ino has type ino_t in both - FreeBSD uses non-fixed-width types for st_mode, st_nlink and st_flags. o struct stat12, for NetBSD-1.2. This is under __LIBC12 || _KERNEL. It uses non-fixed-width types more. It seems to be compatible with FreeBSD struct stat and struct nstat, except FreeBSD has st_birthtime and the end where NetBSD has 2 int64_t spares, and none of these struct is careful enough about padding to ensure binary compatibility on all possible arches. o struct stat, for NetBSD (2005). This uses more non-fixed-width type but is otherwise more careful about padding, using methods that I don't like (it restores the old timespec ifdefs, which have longs which cause padding problems...). This now has st_birthtime, so FreeBSD struct stat might be fully compatible with it, but the wide use of non-fixed-width types and different padding methods make this unclear. This size of struct timespec is arch-dependent, so no one has binary compatibility across arches despite most of the typedefs reducing to the same fixed-width types (time_t and long within struct timespec are the main or only exceptions; `long' there is a historical mistake that was unfortunately standardized). > $ svngrep -Er 'nl?stat\(' /usr/src/ > /usr/src/sys/kern/kern_descrip.c: cvtnstat(&ub, &nub); > /usr/src/sys/kern/syscalls.master:278 AUE_STAT STD { int nstat(char > *path, struct nstat *ub); } > /usr/src/sys/kern/syscalls.master:280 AUE_LSTAT STD { int nlstat(char > *path, struct nstat *ub); } Since they are in syscalls.master... > /usr/src/sys/kern/vfs_syscalls.c:cvtnstat(sb, nsb) > /usr/src/sys/kern/vfs_syscalls.c:nstat(td, uap) > /usr/src/sys/kern/vfs_syscalls.c: cvtnstat(&sb, &nsb); > /usr/src/sys/kern/vfs_syscalls.c:nlstat(td, uap) > /usr/src/sys/kern/vfs_syscalls.c: cvtnstat(&sb, &nsb); ...and not under any COMPAT* ifdef in vfs_syscalls.c (?), they can be used by any binary that wants to use them. > And seems like it should be superseded by lstat, et all, which > were introduced a little earlier on [1]. > Do they serve a real purpose of some kind today? It was introduced > in the revision seen in SVN here [2], and looking back in time there > isn't reference to a NetBSD compat layer in sys/conf/options [3], etc, > so I was a bit curious why there are dangling undocumented (but > publicly visible via sysproto.h) VFS-related syscalls entries hanging > around (in particular because the syscalls aren't declared that way in > NetBSD either). sysproto.h isn't public (it is kernel-only). The only publication errors seem to be the declarations in sys/stat.h discussed above, and the SYS_* entries in sys/syscall.h (old syscalls are supposed to by marked up in syscalls.master so that they don't escape). SYS_nstat is 278, which is for __stat13 in NetBSD, so it has a chance of working. SYS_ostat is 38 (except it is intentionally not defined in syscall.h, which is for compat_43_stat43 in NetBSD, so it too has a chance of working. Ordinary SYS_stat is 188 in FreeBSD, but in NetBSD #188 is compat_12_stat12. These seem to differe mainly in support for st_birthtime. FreeBSD didn't change the syscall for st_birthtime, but this shouldn't cause problems since stat() is read-only so there is no problem with callers passing garbage in st_birthtime. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110214182441.X1003>