--- linux-2.4.21/fs/nfs/inode.c.org 2004-04-17 18:26:32.000000000 -0400 +++ linux-2.4.21/fs/nfs/inode.c 2004-04-23 14:44:59.000000000 -0400 @@ -953,13 +953,74 @@ nfs_wait_on_inode(struct inode *inode, i } /* + * Reinstantiate an inode that has gone stale + */ +static int +nfs_reinstantiate( + struct inode *dir, + struct dentry *dentry, + struct nfs_fattr *fattr) +{ + int error; + struct nfs_fh fhandle; + struct inode *inode; + + /* + * We can only reinstantiate the inode if we are the + * only ones accessing it. + */ + if (atomic_read(&dentry->d_count) > 1) + return EACCES; + + error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); + if (!error) { + error = -ENOMEM; + inode = nfs_fhget(dentry, &fhandle, &fattr); + if (inode) { + /* + * Check again this time holding the i_sem semaphore + * to make sure we are the only ones accessing this + * dentry + */ + down(&dir->i_sem); + if (atomic_read(&dentry->d_count) < 2) { + d_drop(dentry); + dput(dentry); + d_instantiate(dentry, inode); + dentry->d_time = jiffies; + error = 0; + } else + iput(inode); + up(&dir->i_sem); + } + } + return error; +} + +/* * Externally visible revalidation function */ int nfs_revalidate(struct dentry *dentry) { struct inode *inode = dentry->d_inode; - return nfs_revalidate_inode(NFS_SERVER(inode), inode); + struct inode *pinode; + struct nfs_fattr fattr; + int error; + + error = nfs_revalidate_inode(NFS_SERVER(inode), inode); + if (!error || error != -ESTALE) + return error; + /* + * We have a stale fh so ask the server for another one + */ + pinode = dentry->d_parent->d_inode; + if (nfs_reinstantiate(pinode, dentry, &fattr) == 0) { + inode = dentry->d_inode; + if (nfs_refresh_inode(inode, &fattr) == 0) + error = 0; + } + return error; } /*