forsyth@minster.york.ac.uk (05/11/89)
There is a nasty bug in nfs_remove (in nfs/nfs_vnodeops.c). It accepts a directory vnode pointer & a file name and removes the file from the directory. It does an nfs_lookup on the name to produce a vnode pointer for the file. It assumes that will also be an NFS vnode. Unfortunately, owing to the way that special files were hacked into the vnode system and NFS as an afterthought, the vnode need not be an rnode (NFS vnode), since it might be an snode (block or char device vnode) or a fifonode (variant of snode for FIFOs). [nfs_lookup calls specvp if it finds a special file.] But that's all right, since nfs_remove gamely treats it as one of its own, and if the vnode is still open modifies the r_unldvp and r_unlname fields of the supposed rnode. Unfortunately, if the node is in fact a fifonode, that damages the fn_bufend field and this causes fifo_buffree to scribble on things or simply blow up when the file is eventually closed. Even if the file is closed, nfs_remove calls nfsattr_inval(vp), which might be benign, but I should not like to rely on it. The quickest fix is to add #define ISNFS(vp) ((vp)->v_op == &nfs_vnodeops) and use it at obvious points. So much for abstraction. I noticed this because a program that used FIFOs crashed the system when the fifo was removed whilst open with data in it. It was surprisingly hard to track down, not least because of the messy and clumsy nature of fifo_vnodeops.c. It goes to considerable effort to avoid a few #ifdefs in the code; they would be clearer than the hideous rigging of fifonode::fn_bufend and fifo_bufhdr::fb_next to save 4 bytes per fifo block if FIFOBUF == FIFOBSZ. (Those without source can look at specfs/fifo.h to get the flavour.) The result: the most obscure and complicated code I have ever seen to handle a FIFO queue.
berliner@uunet.uu.net (Brian Berliner) (05/27/89)
In Sun-Spots Digest v7n304, forsyth@minster.york.ac.uk notes a bug in the NFS unlink case where the unlinked file is a FIFO special file. In 3.X versions of SunOS, this would usually case a kernel panic if the FIFO that is being unlinked is currently open (3.5 *may* have fixed this... don't know). You can be certain that this is fixed properly starting with 4.0. And the fix is in fact the correct one; a new vnode operation was added to return the real vnode pointer, VOP_REALVP(), to correctly get back to an NFS vnode that has an rnode attached. So all works well. Brian Berliner Prisma, Inc. berliner@prisma.com