From: Trond Myklebust <trond.myklebust@fys.uio.no>


NFSv4: Don't translate those NFSv4 errors that are needed by the kernel
itself into EIO.

NFSv4: Fix a signed/unsigned bug in nfs4_increment_seqid.



---

 fs/nfs/nfs4state.c     |    4 +-
 fs/nfs/nfs4xdr.c       |   63 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/nfs4.h   |   70 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/nfs_fs.h |    2 -
 4 files changed, 135 insertions(+), 4 deletions(-)

diff -puN fs/nfs/nfs4state.c~nfs-22-errno fs/nfs/nfs4state.c
--- 25/fs/nfs/nfs4state.c~nfs-22-errno	2004-01-14 02:09:53.000000000 -0800
+++ 25-akpm/fs/nfs/nfs4state.c	2004-01-14 02:09:53.000000000 -0800
@@ -376,9 +376,9 @@ nfs4_put_open_state(struct nfs4_state *s
 * see comments nfs_fs.h:seqid_mutating_error()
 */
 void
-nfs4_increment_seqid(u32 status, struct nfs4_state_owner *sp)
+nfs4_increment_seqid(int status, struct nfs4_state_owner *sp)
 {
-	if (status == NFS_OK || seqid_mutating_err(status))
+	if (status == NFS_OK || seqid_mutating_err(-status))
 		sp->so_seqid++;
 }
 
diff -puN fs/nfs/nfs4xdr.c~nfs-22-errno fs/nfs/nfs4xdr.c
--- 25/fs/nfs/nfs4xdr.c~nfs-22-errno	2004-01-14 02:09:53.000000000 -0800
+++ 25-akpm/fs/nfs/nfs4xdr.c	2004-01-14 02:09:53.000000000 -0800
@@ -57,7 +57,7 @@
 /* Mapping from NFS error code to "errno" error code. */
 #define errno_NFSERR_IO		EIO
 
-extern int			nfs_stat_to_errno(int);
+static int nfs_stat_to_errno(int);
 
 /* NFSv4 COMPOUND tags are only wanted for debugging purposes */
 #ifdef DEBUG
@@ -2650,6 +2650,67 @@ nfs4_decode_dirent(uint32_t *p, struct n
 	return p;
 }
 
+/*
+ * We need to translate between nfs status return values and
+ * the local errno values which may not be the same.
+ */
+static struct {
+	int stat;
+	int errno;
+} nfs_errtbl[] = {
+	{ NFS4_OK,		0		},
+	{ NFS4ERR_PERM,		EPERM		},
+	{ NFS4ERR_NOENT,	ENOENT		},
+	{ NFS4ERR_IO,		errno_NFSERR_IO	},
+	{ NFS4ERR_NXIO,		ENXIO		},
+	{ NFS4ERR_ACCESS,	EACCES		},
+	{ NFS4ERR_EXIST,	EEXIST		},
+	{ NFS4ERR_XDEV,		EXDEV		},
+	{ NFS4ERR_NOTDIR,	ENOTDIR		},
+	{ NFS4ERR_ISDIR,	EISDIR		},
+	{ NFS4ERR_INVAL,	EINVAL		},
+	{ NFS4ERR_FBIG,		EFBIG		},
+	{ NFS4ERR_NOSPC,	ENOSPC		},
+	{ NFS4ERR_ROFS,		EROFS		},
+	{ NFS4ERR_MLINK,	EMLINK		},
+	{ NFS4ERR_NAMETOOLONG,	ENAMETOOLONG	},
+	{ NFS4ERR_NOTEMPTY,	ENOTEMPTY	},
+	{ NFS4ERR_DQUOT,	EDQUOT		},
+	{ NFS4ERR_STALE,	ESTALE		},
+	{ NFS4ERR_BADHANDLE,	EBADHANDLE	},
+	{ NFS4ERR_BAD_COOKIE,	EBADCOOKIE	},
+	{ NFS4ERR_NOTSUPP,	ENOTSUPP	},
+	{ NFS4ERR_TOOSMALL,	ETOOSMALL	},
+	{ NFS4ERR_SERVERFAULT,	ESERVERFAULT	},
+	{ NFS4ERR_BADTYPE,	EBADTYPE	},
+	{ NFS4ERR_LOCKED,	EAGAIN		},
+	{ NFS4ERR_RESOURCE,	EREMOTEIO	},
+	{ NFS4ERR_SYMLINK,	ELOOP		},
+	{ NFS4ERR_OP_ILLEGAL,	EOPNOTSUPP	},
+	{ NFS4ERR_DEADLOCK,	EDEADLK		},
+	{ -1,			EIO		}
+};
+
+/*
+ * Convert an NFS error code to a local one.
+ * This one is used jointly by NFSv2 and NFSv3.
+ */
+static int
+nfs_stat_to_errno(int stat)
+{
+	int i;
+	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
+		if (nfs_errtbl[i].stat == stat)
+			return nfs_errtbl[i].errno;
+	}
+	/* If we cannot translate the error, the recovery routines should
+	 * handle it.
+	 * Note: remaining NFSv4 error codes have values > 10000, so should
+	 * not conflict with native Linux error codes.
+	 */
+	return stat;
+}
+
 #ifndef MAX
 # define MAX(a, b)	(((a) > (b))? (a) : (b))
 #endif
diff -puN include/linux/nfs4.h~nfs-22-errno include/linux/nfs4.h
--- 25/include/linux/nfs4.h~nfs-22-errno	2004-01-14 02:09:53.000000000 -0800
+++ 25-akpm/include/linux/nfs4.h	2004-01-14 02:09:53.000000000 -0800
@@ -88,6 +88,76 @@ enum nfs_opnum4 {
 	OP_WRITE = 38,
 };
 
+enum nfsstat4 {
+	NFS4_OK = 0,
+	NFS4ERR_PERM = 1,
+	NFS4ERR_NOENT = 2,
+	NFS4ERR_IO = 5,
+	NFS4ERR_NXIO = 6,
+	NFS4ERR_ACCESS = 13,
+	NFS4ERR_EXIST = 17,
+	NFS4ERR_XDEV = 18,
+	/* Unused/reserved 19 */
+	NFS4ERR_NOTDIR = 20,
+	NFS4ERR_ISDIR = 21,
+	NFS4ERR_INVAL = 22,
+	NFS4ERR_FBIG = 27,
+	NFS4ERR_NOSPC = 28,
+	NFS4ERR_ROFS = 30,
+	NFS4ERR_MLINK = 31,
+	NFS4ERR_NAMETOOLONG = 63,
+	NFS4ERR_NOTEMPTY = 66,
+	NFS4ERR_DQUOT = 69,
+	NFS4ERR_STALE = 70,
+	NFS4ERR_BADHANDLE = 10001,
+	NFS4ERR_BAD_COOKIE = 10003,
+	NFS4ERR_NOTSUPP = 10004,
+	NFS4ERR_TOOSMALL = 10005,
+	NFS4ERR_SERVERFAULT = 10006,
+	NFS4ERR_BADTYPE = 10007,
+	NFS4ERR_DELAY = 10008,
+	NFS4ERR_SAME = 10009,
+	NFS4ERR_DENIED = 10010,
+	NFS4ERR_EXPIRED = 10011,
+	NFS4ERR_LOCKED = 10012,
+	NFS4ERR_GRACE = 10013,
+	NFS4ERR_FHEXPIRED = 10014,
+	NFS4ERR_SHARE_DENIED = 10015,
+	NFS4ERR_WRONGSEC = 10016,
+	NFS4ERR_CLID_INUSE = 10017,
+	NFS4ERR_RESOURCE = 10018,
+	NFS4ERR_MOVED = 10019,
+	NFS4ERR_NOFILEHANDLE = 10020,
+	NFS4ERR_MINOR_VERS_MISMATCH = 10021,
+	NFS4ERR_STALE_CLIENTID = 10022,
+	NFS4ERR_STALE_STATEID = 10023,
+	NFS4ERR_OLD_STATEID = 10024,
+	NFS4ERR_BAD_STATEID = 10025,
+	NFS4ERR_BAD_SEQID = 10026,
+	NFS4ERR_NOT_SAME = 10027,
+	NFS4ERR_LOCK_RANGE = 10028,
+	NFS4ERR_SYMLINK = 10029,
+	NFS4ERR_RESTOREFH = 10030,
+	NFS4ERR_LEASE_MOVED = 10031,
+	NFS4ERR_ATTRNOTSUPP = 10032,
+	NFS4ERR_NO_GRACE = 10033,
+	NFS4ERR_RECLAIM_BAD = 10034,
+	NFS4ERR_RECLAIM_CONFLICT = 10035,
+	NFS4ERR_BADXDR = 10036,
+	NFS4ERR_LOCKS_HELD = 10037,
+	NFS4ERR_OPENMODE = 10038,
+	NFS4ERR_BADOWNER = 10039,
+	NFS4ERR_BADCHAR = 10040,
+	NFS4ERR_BADNAME = 10041,
+	NFS4ERR_BAD_RANGE = 10042,
+	NFS4ERR_LOCK_NOTSUPP = 10043,
+	NFS4ERR_OP_ILLEGAL = 10044,
+	NFS4ERR_DEADLOCK = 10045,
+	NFS4ERR_FILE_OPEN = 10046,
+	NFS4ERR_ADMIN_REVOKED = 10047,
+	NFS4ERR_CB_PATH_DOWN = 10048
+};
+
 /*
  * Note: NF4BAD is not actually part of the protocol; it is just used
  * internally by nfsd.
diff -puN include/linux/nfs_fs.h~nfs-22-errno include/linux/nfs_fs.h
--- 25/include/linux/nfs_fs.h~nfs-22-errno	2004-01-14 02:09:53.000000000 -0800
+++ 25-akpm/include/linux/nfs_fs.h	2004-01-14 02:09:53.000000000 -0800
@@ -571,7 +571,7 @@ extern struct nfs4_state_owner * nfs4_ge
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_increment_seqid(u32 status, struct nfs4_state_owner *sp);
+extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
 
 struct nfs4_mount_data;
 #else

_