Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Dec 1996 11:33:20 -0500 (EST)
From:      Bill Paul <wpaul@skynet.ctr.columbia.edu>
To:        joerg_wunsch@uriah.heep.sax.de
Cc:        hackers@freebsd.org
Subject:   Re: [2.2-BETA] NFS hangup!
Message-ID:  <199612271633.LAA21311@skynet.ctr.columbia.edu>
In-Reply-To: <199612270856.JAA03454@uriah.heep.sax.de> from "J Wunsch" at Dec 27, 96 09:56:03 am

next in thread | previous in thread | raw e-mail | index | archive | help
Of all the gin joints in all the towns in all the world, J Wunsch had to 
walk into mine and say:

> As Naoki Hamada wrote:
> 
> > This morning I encountered a sudden hangup and found out what is the
> > case. On a NFS imported filesystem, when I execute the following
> > sequence, the PC totally hangs up after the `mv' command.
> > 
> > % mkdir -p tmp/tmp
> > % mv tmp/tmp .
> 
> I get the dreaded
> 
> panic: nfs: sillyrename dir
> 
> when trying this.  (Both, client and server are FreeBSD.)
> 
> Doesn't this ring a bell for somebody?

Happens for me too (SunOS 4.1.3 server, FreeBSD client). The offending
code is in nfs_vnops.c:

static int
nfs_sillyrename(dvp, vp, cnp)
        struct vnode *dvp, *vp;
        struct componentname *cnp;
{
        register struct sillyrename *sp;
        struct nfsnode *np;
        int error;
        short pid;

        cache_purge(dvp);
        np = VTONFS(vp);
#ifndef DIAGNOSTIC
        if (vp->v_type == VDIR)
                panic("nfs: sillyrename dir");
#endif

It's basically disallowing sillyrenames for directories. If you compile
with options DIAGNOSTIC it looks like the problem is hidden; this doesn't
look like the right thing to do though.

With SunOS, I get:

mv: tmp/tmp: rename: Directory not empty

Looking at our code, it seems that the client will attempt a sillyrename
in nfs_rename() if the 'destination' vnode exists is in use. The 2.1.0
code didn't do this (which I guess is a bug if you're renaming foo to bar,
and foo and bar are both files, and bar exists and is still being 
referenced by someone). (Of course none of this crap works if you have 
two client machines, and a process on one host unlinks bar while a 
process on the other host has a reference to bar, but that's NFS for 
you.) The code in nfs_rename() says:

        /* 
         * If the tvp exists and is in use, sillyrename it before doing the
         * rename of the new file over it.
         */     
        if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
                !nfs_sillyrename(tdvp, tvp, tcnp)) {
                vrele(tvp);
                tvp = NULL;
        }


Should the test in nfs_rename() check if the 'destination' vnode is a 
directory and skip the sillyrename if it is? I.e.:

        /* 
         * If the tvp exists and is in use, sillyrename it before doing the
         * rename of the new file over it.
         * XXX Can't sillyrename a directory. The server will catch the
         * error for us anyway.
         */     
        if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
                tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
                vrele(tvp);
                tvp = NULL;
        }


-Bill

-- 
=============================================================================
-Bill Paul            (212) 854-6020 | System Manager, Master of Unix-Fu
Work:         wpaul@ctr.columbia.edu | Center for Telecommunications Research
Home:  wpaul@skynet.ctr.columbia.edu | Columbia University, New York City
=============================================================================
 "It is not I who am crazy; it is I who am mad!" - Ren Hoek, "Space Madness"
=============================================================================



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612271633.LAA21311>