link() not increasing link count on NFS server

Gavin Atkinson gavin.atkinson at
Fri Nov 16 06:47:20 PST 2007

On Thu, 2007-11-15 at 14:05 +0000, Robert Watson wrote:
> On Thu, 15 Nov 2007, Timo Sirainen wrote:
> > On Thu, 2007-11-15 at 12:39 +0000, Robert Watson wrote:
> >
> >>> or Solaris NFS clients. Basically, Timo (cc'ed) came up with a small test 
> >>> case that seems to indicate sometimes a link() call can succeed while the 
> >>> link count of the file will not increase.  If this is ran on two FreeBSD 
> >>> clients from the same NFS directory, you will occasionally see "link() 
> >>> succeeded, but link count=1".  I've tried both a Netapp and a FreeBSD NFS
> > ..
> >> My guess, and this is just a hand-wave, is that the attribute cache in the 
> >> NFS client isn't being forced to refresh, and hence you're getting the old 
> >> stat data back (and perhaps there's no GETATTR on the wire, which might 
> >> hint at this).  If you'd like, you can post a link to the pcap capture file 
> >> and one of us can take a look, but I've found NFS RPCs to be surprisingly 
> >> readable in Wireshark so you might find it sheds quite a bit of light.
> >
> > Actually the point was that link() returns success even though in reality it 
> > fails. The fstat() was just a workaround to catch this case and treat link 
> > count 1 as if link() had failed with EEXIST. After that I had no more 
> > problems with locking.
> >
> > I noticed this first because my dotlocking was failing to lock files 
> > properly. I also added fchown() to flush attribute cache after link() and 
> > before fstat(), it gives the same link count=1 reply.
> Indeed, and inspection of nfs_vnops.c:nfs_link(): finds:
> 1772         /*
> 1773          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
> 1774          */
> 1775         if (error == EEXIST)
> 1776                 error = 0;
> 1777         return (error);
> Neither Linux nor Solaris appears to have this logic in the client.  I assume 
> this is, as suggested, to work around UDP retransmissions where the reply is 
> lost rather than the request.  It appears to exist in revision 1.1 of 
> nfs_vnops.c, so came in with 4.4BSD in the initial import, but doesn't appear 
> in NetBSD so I'm guessing they've removed it.  It could well be we should be 
> doing the same.

Small point - NetBSD does seem to still have this code, but they have
factored it out into a nfs_linkrpc function.  I'm not saying it's
correct, however...


More information about the freebsd-current mailing list