diff -urN 2.2.19pre7/fs/nfsd/nfsfh.c z/fs/nfsd/nfsfh.c --- 2.2.19pre7/fs/nfsd/nfsfh.c Mon Dec 11 16:58:01 2000 +++ z/fs/nfsd/nfsfh.c Wed Jan 10 15:08:39 2001 @@ -339,7 +339,7 @@ struct dentry *dentry, *result = NULL; struct dentry *tmp; int found =0; - int err; + int err = -ESTALE; /* the sb->s_nfsd_free_path_sem semaphore is needed to make sure that only one unconnected (free) * dcache path ever exists, as otherwise two partial paths might get * joined together, which would be very confusing. @@ -353,23 +353,21 @@ * Attempt to find the inode. */ retry: + down(&sb->s_nfsd_free_path_sem); result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation); - err = PTR_ERR(result); - if (IS_ERR(result)) - goto err_out; - err = -ESTALE; - if (!result) { - dprintk("find_fh_dentry: No inode found.\n"); - goto err_out; - } - if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) - return result; - - /* result is now an anonymous dentry, which may be adequate as it - * stands, or else will get spliced into the dcache tree */ - - if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) { - nfsdstats.fh_anon++; + if (!result || IS_ERR(result) + || !(result->d_flags & DCACHE_NFSD_DISCONNECTED) + || (!S_ISDIR(result->d_inode->i_mode) && !needpath)) { + up(&sb->s_nfsd_free_path_sem); + if (!result) { + dprintk("find_fh_dentry: No inode found.\n"); + goto err_out; + } + err = PTR_ERR(result); + if (IS_ERR(result)) + goto err_out; + if ( (result->d_flags & DCACHE_NFSD_DISCONNECTED)) + nfsdstats.fh_anon++; return result; } @@ -377,14 +375,6 @@ * location in the tree. */ dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino); - down(&sb->s_nfsd_free_path_sem); - - /* claiming the semaphore might have allow things to get fixed up */ - if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) { - up(&sb->s_nfsd_free_path_sem); - return result; - } - found = 0; if (!S_ISDIR(result->d_inode->i_mode)) {