From: NeilBrown <neilb@cse.unsw.edu.au>

unlike v2/v3, nfsv4 returns nfserr_exist in some situations where the
underlying filesystem returns nfserr_isdir, nfserr_notdir.

on rename, nfsv4 returns nfserr_notdir instead of nfserr_symlink.


---

 25-akpm/fs/nfsd/nfs4proc.c |   12 ++++++++++++
 1 files changed, 12 insertions(+)

diff -puN fs/nfsd/nfs4proc.c~knfsd-rename-error-code-fixes fs/nfsd/nfs4proc.c
--- 25/fs/nfsd/nfs4proc.c~knfsd-rename-error-code-fixes	Mon Feb 23 16:33:49 2004
+++ 25-akpm/fs/nfsd/nfs4proc.c	Mon Feb 23 16:33:49 2004
@@ -476,6 +476,18 @@ nfsd4_rename(struct svc_rqst *rqstp, str
 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
 			     rename->rn_snamelen, current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
+
+	/* the underlying filesystem returns different error's than required
+	 * by NFSv4. both save_fh and current_fh have been verified.. */
+	if (status == nfserr_isdir)
+		status = nfserr_exist;
+	else if ((status == nfserr_notdir) &&
+                  (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
+                   S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+		status = nfserr_exist;
+	else if (status == nfserr_symlink)
+		status = nfserr_notdir;
+
 	if (!status) {
 		set_change_info(&rename->rn_sinfo, current_fh);
 		set_change_info(&rename->rn_tinfo, save_fh);

_