diff -urN nfsd-ref/fs/nfsd/nfsfh.c nfsd/fs/nfsd/nfsfh.c --- nfsd-ref/fs/nfsd/nfsfh.c Sun Dec 24 17:09:05 2000 +++ nfsd/fs/nfsd/nfsfh.c Sun Dec 24 17:09:26 2000 @@ -332,7 +332,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. @@ -351,15 +351,14 @@ if (!result || IS_ERR(result) || !(result->d_flags & DCACHE_NFSD_DISCONNECTED) || (!S_ISDIR(result->d_inode->i_mode) && !needpath)) { - up(&sb->nfsd_free_path_sem); - err = PTR_ERR(result); - if (IS_ERR(result)) - goto err_out; - err = -ESTALE; + 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; diff -urN nfsd-ref/fs/nfsd/vfs.c nfsd/fs/nfsd/vfs.c --- nfsd-ref/fs/nfsd/vfs.c Sun Dec 24 17:09:05 2000 +++ nfsd/fs/nfsd/vfs.c Sun Dec 24 17:09:26 2000 @@ -412,8 +412,16 @@ }; static struct accessmap nfs3_anyaccess[] = { - /* XXX: should we try to cover read/write here for clients that - * rely on us to do their access checking for special files? */ + /* Some clients - Solaris 2.6 at least, make an access call + * to the server to check for access for things like /dev/null + * (which really, the server doesn't care about). So + * We provide simple access checking for them, looking + * mainly at mode bits + */ + { NFS3_ACCESS_READ, MAY_READ }, + { NFS3_ACCESS_EXECUTE, MAY_EXEC }, + { NFS3_ACCESS_MODIFY, MAY_WRITE }, + { NFS3_ACCESS_EXTEND, MAY_WRITE }, { 0, 0 } }; @@ -1738,12 +1746,17 @@ inode->i_uid, inode->i_gid, current->fsuid, current->fsgid); #endif - if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { - if (EX_RDONLY(exp) || IS_RDONLY(inode)) - return nfserr_rofs; - if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) - return nfserr_perm; - } + /* only care about readonly exports for files and + * directories. links don't have meaningful write access, + * and all else is local to the client + */ + if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)) + if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) { + if (EX_RDONLY(exp) || IS_RDONLY(inode)) + return nfserr_rofs; + if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode)) + return nfserr_perm; + } if ((acc & MAY_TRUNC) && IS_APPEND(inode)) return nfserr_perm;