From a6ce8d7c4dd13e285dc96197ba09636666d0d93c Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 25 Sep 2005 00:20:38 +0000 Subject: [PATCH] Convert from nfs error values to regular errno's. Although most values of nfs errors are chosen to be the same as errno, some of them are not and it is better for portability to do the conversion anyway. Also a server can return a bad error number that can cause the server to crash, because it can have the high bits that are used internally set. This was the case with amd. Finally nfs_request() should return a valid errno, because we can return a bogus value to userland. Thanks to rpaulo for debugging this. --- sys/nfs/nfs_socket.c | 131 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 118 insertions(+), 13 deletions(-) diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index b6b56f634cce..eb4172bf5e8f 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -1,4 +1,4 @@ -/* $NetBSD: nfs_socket.c,v 1.114 2005/05/29 20:58:13 christos Exp $ */ +/* $NetBSD: nfs_socket.c,v 1.115 2005/09/25 00:20:38 christos Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1995 @@ -39,7 +39,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.114 2005/05/29 20:58:13 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.115 2005/09/25 00:20:38 christos Exp $"); #include "fs_nfs.h" #include "opt_nfs.h" @@ -1211,22 +1211,122 @@ tryagain: nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); if (*tl != 0) { error = fxdr_unsigned(int, *tl); - if (error == NFSERR_ACCES && retry_cred) { + switch (error) { + case NFSERR_PERM: + error = EPERM; + break; + + case NFSERR_NOENT: + error = ENOENT; + break; + + case NFSERR_NXIO: + error = ENXIO; + break; + + case NFSERR_ACCES: + error = EACCES; + if (!retry_cred) + break; m_freem(mrep); m_freem(rep->r_mreq); FREE(rep, M_NFSREQ); use_opencred = !use_opencred; if (mrest_backup == NULL) - return ENOMEM; /* m_copym failure */ + /* m_copym failure */ + return ENOMEM; mrest = mrest_backup; mrest_backup = NULL; cred = origcred; error = 0; retry_cred = FALSE; goto tryagain_cred; - } - if ((nmp->nm_flag & NFSMNT_NFSV3) && - error == NFSERR_TRYLATER) { + + case NFSERR_EXIST: + error = EEXIST; + break; + + case NFSERR_XDEV: + error = EXDEV; + break; + + case NFSERR_NODEV: + error = ENODEV; + break; + + case NFSERR_NOTDIR: + error = ENOTDIR; + break; + + case NFSERR_ISDIR: + error = EISDIR; + break; + + case NFSERR_INVAL: + error = EINVAL; + break; + + case NFSERR_FBIG: + error = EFBIG; + break; + + case NFSERR_NOSPC: + error = ENOSPC; + break; + + case NFSERR_ROFS: + error = EROFS; + break; + + case NFSERR_MLINK: + error = EMLINK; + break; + + case NFSERR_NAMETOL: + error = ENAMETOOLONG; + break; + + case NFSERR_NOTEMPTY: + error = ENOTEMPTY; + break; + + case NFSERR_DQUOT: + error = EDQUOT; + break; + + case NFSERR_STALE: + /* + * If the File Handle was stale, invalidate the + * lookup cache, just in case. + */ + error = ESTALE; + cache_purge(NFSTOV(np)); + break; + + case NFSERR_REMOTE: + error = EREMOTE; + break; + + case NFSERR_WFLUSH: + case NFSERR_BADHANDLE: + case NFSERR_NOT_SYNC: + case NFSERR_BAD_COOKIE: + error = EINVAL; + break; + + case NFSERR_NOTSUPP: + error = ENOTSUP; + break; + + case NFSERR_TOOSMALL: + case NFSERR_SERVERFAULT: + case NFSERR_BADTYPE: + error = EINVAL; + break; + + case NFSERR_TRYLATER: + if ((nmp->nm_flag & NFSMNT_NFSV3) == 0) + break; m_freem(mrep); error = 0; waituntil = time.tv_sec + trylater_delay; @@ -1243,14 +1343,19 @@ tryagain: */ nfs_renewxid(rep); goto tryagain; + + case NFSERR_STALEWRITEVERF: + error = EINVAL; + break; + + default: +#ifdef DIAGNOSTIC + printf("Invalid rpc error code %d\n", error); +#endif + error = EINVAL; + break; } - /* - * If the File Handle was stale, invalidate the - * lookup cache, just in case. - */ - if (error == ESTALE) - cache_purge(NFSTOV(np)); if (nmp->nm_flag & NFSMNT_NFSV3) { *mrp = mrep; *mdp = md;