summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/devfs/devfs_vnops.c18
-rw-r--r--sys/fs/nfs/nfs_commonacl.c38
-rw-r--r--sys/fs/nfs/nfs_commonkrpc.c112
-rw-r--r--sys/fs/nfs/nfs_commonport.c59
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c246
-rw-r--r--sys/fs/nfs/nfs_var.h5
-rw-r--r--sys/fs/nfs/nfsdport.h16
-rw-r--r--sys/fs/nfs/nfsport.h13
-rw-r--r--sys/fs/nfs/nfsproto.h57
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c7
-rw-r--r--sys/fs/nfsclient/nfs_clkdtrace.c600
-rw-r--r--sys/fs/nfsclient/nfs_clkrpc.c12
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c5
-rw-r--r--sys/fs/nfsclient/nfs_clport.c36
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c50
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c181
-rw-r--r--sys/fs/nfsclient/nfs_clsubs.c11
-rw-r--r--sys/fs/nfsclient/nfs_clvfsops.c6
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c108
-rw-r--r--sys/fs/nfsclient/nfs_kdtrace.h120
-rw-r--r--sys/fs/nfsserver/nfs_nfsdcache.c42
-rw-r--r--sys/fs/nfsserver/nfs_nfsdkrpc.c79
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c325
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c411
-rw-r--r--sys/fs/nfsserver/nfs_nfsdsocket.c27
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c396
-rw-r--r--sys/fs/nfsserver/nfs_nfsdsubs.c74
-rw-r--r--sys/fs/smbfs/smbfs_smb.c2
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c2
29 files changed, 2202 insertions, 856 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index bf6dab8..955bd8b 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -397,6 +397,7 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
sx_xunlock(&dmp->dm_lock);
return (ENOENT);
}
+loop:
DEVFS_DE_HOLD(de);
DEVFS_DMP_HOLD(dmp);
mtx_lock(&devfs_de_interlock);
@@ -405,16 +406,21 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, int lockmode,
VI_LOCK(vp);
mtx_unlock(&devfs_de_interlock);
sx_xunlock(&dmp->dm_lock);
- error = vget(vp, lockmode | LK_INTERLOCK, curthread);
+ vget(vp, lockmode | LK_INTERLOCK | LK_RETRY, curthread);
sx_xlock(&dmp->dm_lock);
if (devfs_allocv_drop_refs(0, dmp, de)) {
- if (error == 0)
- vput(vp);
+ vput(vp);
return (ENOENT);
}
- else if (error) {
- sx_xunlock(&dmp->dm_lock);
- return (error);
+ else if ((vp->v_iflag & VI_DOOMED) != 0) {
+ mtx_lock(&devfs_de_interlock);
+ if (de->de_vnode == vp) {
+ de->de_vnode = NULL;
+ vp->v_data = NULL;
+ }
+ mtx_unlock(&devfs_de_interlock);
+ vput(vp);
+ goto loop;
}
sx_xunlock(&dmp->dm_lock);
*vpp = vp;
diff --git a/sys/fs/nfs/nfs_commonacl.c b/sys/fs/nfs/nfs_commonacl.c
index c4875d8..1d731c5 100644
--- a/sys/fs/nfs/nfs_commonacl.c
+++ b/sys/fs/nfs/nfs_commonacl.c
@@ -59,7 +59,8 @@ nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
mask = fxdr_unsigned(u_int32_t, *tl++);
len = fxdr_unsigned(int, *tl);
if (len < 0) {
- return (NFSERR_BADXDR);
+ error = NFSERR_BADXDR;
+ goto nfsmout;
} else if (len == 0) {
/* Netapp filers return a 0 length who for nil users */
acep->ae_tag = ACL_UNDEFINED_TAG;
@@ -68,7 +69,8 @@ nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
acep->ae_entry_type = ACL_ENTRY_TYPE_DENY;
if (acesizep)
*acesizep = 4 * NFSX_UNSIGNED;
- return (0);
+ error = 0;
+ goto nfsmout;
}
if (len > NFSV4_SMALLSTR)
name = malloc(len + 1, M_NFSSTRING, M_WAITOK);
@@ -78,7 +80,7 @@ nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
if (error) {
if (len > NFSV4_SMALLSTR)
free(name, M_NFSSTRING);
- return (error);
+ goto nfsmout;
}
if (len == 6) {
if (!NFSBCMP(name, "OWNER@", 6)) {
@@ -171,8 +173,9 @@ nfsrv_dissectace(struct nfsrv_descript *nd, struct acl_entry *acep,
*aceerrp = aceerr;
if (acesizep)
*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
- return (0);
+ error = 0;
nfsmout:
+ NFSEXITCODE(error);
return (error);
}
@@ -184,6 +187,7 @@ nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
enum vtype type, acl_perm_t *permp)
{
acl_perm_t perm = 0x0;
+ int error = 0;
if (mask & NFSV4ACE_READDATA) {
mask &= ~NFSV4ACE_READDATA;
@@ -257,10 +261,15 @@ nfsrv_acemasktoperm(u_int32_t acetype, u_int32_t mask, int owner,
mask &= ~NFSV4ACE_SYNCHRONIZE;
perm |= ACL_SYNCHRONIZE;
}
- if (mask != 0)
- return (NFSERR_ATTRNOTSUPP);
+ if (mask != 0) {
+ error = NFSERR_ATTRNOTSUPP;
+ goto out;
+ }
*permp = perm;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/* local functions */
@@ -445,19 +454,26 @@ nfsrv_setacl(vnode_t vp, NFSACL_T *aclp, struct ucred *cred,
{
int error;
- if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0)
- return (NFSERR_ATTRNOTSUPP);
+ if (nfsrv_useacl == 0 || nfs_supportsnfsv4acls(vp) == 0) {
+ error = NFSERR_ATTRNOTSUPP;
+ goto out;
+ }
/*
* With NFSv4 ACLs, chmod(2) may need to add additional entries.
* Make sure it has enough room for that - splitting every entry
* into two and appending "canonical six" entries at the end.
* Cribbed out of kern/vfs_acl.c - Rick M.
*/
- if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2)
- return (NFSERR_ATTRNOTSUPP);
+ if (aclp->acl_cnt > (ACL_MAX_ENTRIES - 6) / 2) {
+ error = NFSERR_ATTRNOTSUPP;
+ goto out;
+ }
error = VOP_ACLCHECK(vp, ACL_TYPE_NFS4, aclp, cred, p);
if (!error)
error = VOP_SETACL(vp, ACL_TYPE_NFS4, aclp, cred, p);
+
+out:
+ NFSEXITCODE(error);
return (error);
}
diff --git a/sys/fs/nfs/nfs_commonkrpc.c b/sys/fs/nfs/nfs_commonkrpc.c
index ba1ac4e..1f65380 100644
--- a/sys/fs/nfs/nfs_commonkrpc.c
+++ b/sys/fs/nfs/nfs_commonkrpc.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
*/
#include "opt_inet6.h"
+#include "opt_kdtrace.h"
#include "opt_kgssapi.h"
#include "opt_nfs.h"
@@ -64,6 +65,28 @@ __FBSDID("$FreeBSD$");
#include <fs/nfs/nfsport.h>
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+dtrace_nfsclient_nfs23_start_probe_func_t
+ dtrace_nfscl_nfs234_start_probe;
+
+dtrace_nfsclient_nfs23_done_probe_func_t
+ dtrace_nfscl_nfs234_done_probe;
+
+/*
+ * Registered probes by RPC type.
+ */
+uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1];
+uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1];
+
+uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1];
+uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1];
+
+uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1];
+uint32_t nfscl_nfs4_done_probes[NFS_NPROCS + 1];
+#endif
+
NFSSTATESPINLOCK;
NFSREQSPINLOCK;
extern struct nfsstats newnfsstats;
@@ -143,7 +166,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
CLIENT *client;
struct netconfig *nconf;
struct socket *so;
- int one = 1, retries, error;
+ int one = 1, retries, error = 0;
struct thread *td = curthread;
/*
@@ -199,7 +222,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
nrp->nr_soproto, td->td_ucred, td);
if (error) {
td->td_ucred = origcred;
- return (error);
+ goto out;
}
do {
if (error != 0 && pktscale > 2)
@@ -230,7 +253,7 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
soclose(so);
if (error) {
td->td_ucred = origcred;
- return (error);
+ goto out;
}
client = clnt_reconnect_create(nconf, saddr, nrp->nr_prog,
@@ -284,7 +307,10 @@ newnfs_connect(struct nfsmount *nmp, struct nfssockreq *nrp,
/* Restore current thread's credentials. */
td->td_ucred = origcred;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -300,9 +326,7 @@ newnfs_disconnect(struct nfssockreq *nrp)
client = nrp->nr_client;
nrp->nr_client = NULL;
mtx_unlock(&nrp->nr_mtx);
-#ifdef KGSSAPI
- rpc_gss_secpurge(client);
-#endif
+ rpc_gss_secpurge_call(client);
CLNT_CLOSE(client);
CLNT_RELEASE(client);
} else {
@@ -314,21 +338,18 @@ static AUTH *
nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
char *srv_principal, gss_OID mech_oid, struct ucred *cred)
{
-#ifdef KGSSAPI
rpc_gss_service_t svc;
AUTH *auth;
#ifdef notyet
rpc_gss_options_req_t req_options;
#endif
-#endif
switch (secflavour) {
-#ifdef KGSSAPI
case RPCSEC_GSS_KRB5:
case RPCSEC_GSS_KRB5I:
case RPCSEC_GSS_KRB5P:
if (!mech_oid) {
- if (!rpc_gss_mech_to_oid("kerberosv5", &mech_oid))
+ if (!rpc_gss_mech_to_oid_call("kerberosv5", &mech_oid))
return (NULL);
}
if (secflavour == RPCSEC_GSS_KRB5)
@@ -344,7 +365,7 @@ nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
req_options.input_channel_bindings = NULL;
req_options.enc_type = nfs_keytab_enctype;
- auth = rpc_gss_secfind(nrp->nr_client, cred,
+ auth = rpc_gss_secfind_call(nrp->nr_client, cred,
clnt_principal, srv_principal, mech_oid, svc,
&req_options);
#else
@@ -354,7 +375,7 @@ nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
* principals. As such, that case cannot yet be handled.
*/
if (clnt_principal == NULL)
- auth = rpc_gss_secfind(nrp->nr_client, cred,
+ auth = rpc_gss_secfind_call(nrp->nr_client, cred,
srv_principal, mech_oid, svc);
else
auth = NULL;
@@ -362,7 +383,6 @@ nfs_getauth(struct nfssockreq *nrp, int secflavour, char *clnt_principal,
if (auth != NULL)
return (auth);
/* fallthrough */
-#endif /* KGSSAPI */
case AUTH_SYS:
default:
return (authunix_create(cred));
@@ -509,6 +529,20 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
else
secflavour = RPCSEC_GSS_KRB5;
srv_principal = NFSMNT_SRVKRBNAME(nmp);
+ } else if (nmp != NULL && !NFSHASKERB(nmp) &&
+ nd->nd_procnum != NFSPROC_NULL &&
+ (nd->nd_flag & ND_USEGSSNAME) != 0) {
+ /*
+ * Use the uid that did the mount when the RPC is doing
+ * NFSv4 system operations, as indicated by the
+ * ND_USEGSSNAME flag, for the AUTH_SYS case.
+ */
+ saved_uid = cred->cr_uid;
+ if (nmp->nm_uid != (uid_t)-1)
+ cred->cr_uid = nmp->nm_uid;
+ else
+ cred->cr_uid = 0;
+ set_uid = 1;
}
if (nmp != NULL) {
@@ -568,6 +602,29 @@ newnfs_request(struct nfsrv_descript *nd, struct nfsmount *nmp,
if ((nd->nd_flag & ND_NFSV4) && procnum == NFSV4PROC_COMPOUND)
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq),
M_NFSDREQ, M_WAITOK);
+#ifdef KDTRACE_HOOKS
+ if (dtrace_nfscl_nfs234_start_probe != NULL) {
+ uint32_t probe_id;
+ int probe_procnum;
+
+ if (nd->nd_flag & ND_NFSV4) {
+ probe_id =
+ nfscl_nfs4_start_probes[nd->nd_procnum];
+ probe_procnum = nd->nd_procnum;
+ } else if (nd->nd_flag & ND_NFSV3) {
+ probe_id = nfscl_nfs3_start_probes[procnum];
+ probe_procnum = procnum;
+ } else {
+ probe_id =
+ nfscl_nfs2_start_probes[nd->nd_procnum];
+ probe_procnum = procnum;
+ }
+ if (probe_id != 0)
+ (dtrace_nfscl_nfs234_start_probe)
+ (probe_id, vp, nd->nd_mreq, cred,
+ probe_procnum);
+ }
+#endif
}
trycnt = 0;
tryagain:
@@ -658,8 +715,10 @@ tryagain:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nd->nd_repstat = fxdr_unsigned(u_int32_t, *tl);
if (nd->nd_repstat != 0) {
- if ((nd->nd_repstat == NFSERR_DELAY &&
+ if (((nd->nd_repstat == NFSERR_DELAY ||
+ nd->nd_repstat == NFSERR_GRACE) &&
(nd->nd_flag & ND_NFSV4) &&
+ nd->nd_procnum != NFSPROC_DELEGRETURN &&
nd->nd_procnum != NFSPROC_SETATTR &&
nd->nd_procnum != NFSPROC_READ &&
nd->nd_procnum != NFSPROC_WRITE &&
@@ -679,6 +738,8 @@ tryagain:
while (NFSD_MONOSEC < waituntil)
(void) nfs_catnap(PZERO, 0, "nfstry");
trylater_delay *= 2;
+ m_freem(nd->nd_mrep);
+ nd->nd_mrep = NULL;
goto tryagain;
}
@@ -762,6 +823,27 @@ tryagain:
}
}
+#ifdef KDTRACE_HOOKS
+ if (nmp != NULL && dtrace_nfscl_nfs234_done_probe != NULL) {
+ uint32_t probe_id;
+ int probe_procnum;
+
+ if (nd->nd_flag & ND_NFSV4) {
+ probe_id = nfscl_nfs4_done_probes[nd->nd_procnum];
+ probe_procnum = nd->nd_procnum;
+ } else if (nd->nd_flag & ND_NFSV3) {
+ probe_id = nfscl_nfs3_done_probes[procnum];
+ probe_procnum = procnum;
+ } else {
+ probe_id = nfscl_nfs2_done_probes[nd->nd_procnum];
+ probe_procnum = procnum;
+ }
+ if (probe_id != 0)
+ (dtrace_nfscl_nfs234_done_probe)(probe_id, vp,
+ nd->nd_mreq, cred, probe_procnum, 0);
+ }
+#endif
+
m_freem(nd->nd_mreq);
AUTH_DESTROY(auth);
if (rep != NULL)
diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c
index 6254915..0320f47 100644
--- a/sys/fs/nfs/nfs_commonport.c
+++ b/sys/fs/nfs/nfs_commonport.c
@@ -289,6 +289,50 @@ nfsvno_getfs(struct nfsfsinfo *sip, int isdgram)
NFSV3FSINFO_CANSETTIME);
}
+/*
+ * Do the pathconf vnode op.
+ */
+int
+nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf,
+ struct ucred *cred, struct thread *p)
+{
+ int error;
+
+ error = VOP_PATHCONF(vp, flag, retf);
+ if (error == EOPNOTSUPP || error == EINVAL) {
+ /*
+ * Some file systems return EINVAL for name arguments not
+ * supported and some return EOPNOTSUPP for this case.
+ * So the NFSv3 Pathconf RPC doesn't fail for these cases,
+ * just fake them.
+ */
+ switch (flag) {
+ case _PC_LINK_MAX:
+ *retf = LINK_MAX;
+ break;
+ case _PC_NAME_MAX:
+ *retf = NAME_MAX;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ *retf = 1;
+ break;
+ case _PC_NO_TRUNC:
+ *retf = 1;
+ break;
+ default:
+ /*
+ * Only happens if a _PC_xxx is added to the server,
+ * but this isn't updated.
+ */
+ *retf = 0;
+ printf("nfsrvd pathconf flag=%d not supp\n", flag);
+ };
+ error = 0;
+ }
+ NFSEXITCODE(error);
+ return (error);
+}
+
/* Fake nfsrv_atroot. Just return 0 */
int
nfsrv_atroot(struct vnode *vp, long *retp)
@@ -384,6 +428,7 @@ nfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap)
int error;
error = nfssvc_call(td, uap, td->td_ucred);
+ NFSEXITCODE(error);
return (error);
}
@@ -396,9 +441,9 @@ nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
if (uap->flag & NFSSVC_IDNAME) {
error = copyin(uap->argp, (caddr_t)&nid, sizeof (nid));
if (error)
- return (error);
+ goto out;
error = nfssvc_idname(&nid);
- return (error);
+ goto out;
} else if (uap->flag & NFSSVC_GETSTATS) {
error = copyout(&newnfsstats,
CAST_USER_ADDR_T(uap->argp), sizeof (newnfsstats));
@@ -460,7 +505,7 @@ nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
sizeof(newnfsstats.cbrpccnt));
}
}
- return (error);
+ goto out;
} else if (uap->flag & NFSSVC_NFSUSERDPORT) {
u_short sockport;
@@ -472,6 +517,9 @@ nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
nfsrv_nfsuserddelport();
error = 0;
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -526,7 +574,7 @@ nfscommon_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
if (loaded)
- return (0);
+ goto out;
newnfs_portinit();
mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF);
mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF);
@@ -563,6 +611,9 @@ nfscommon_modevent(module_t mod, int type, void *data)
error = EOPNOTSUPP;
break;
}
+
+out:
+ NFSEXITCODE(error);
return error;
}
static moduledata_t nfscommon_mod = {
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 03b5786..168018c 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -179,8 +179,10 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
len = NFSMTOD(mp, caddr_t) + mbuf_len(mp) - mbufcp;
rem = NFSM_RNDUP(siz) - siz;
while (siz > 0) {
- if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
- return (EBADRPC);
+ if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) {
+ error = EBADRPC;
+ goto out;
+ }
left = uiop->uio_iov->iov_len;
uiocp = uiop->uio_iov->iov_base;
if (left > siz)
@@ -189,8 +191,10 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
while (left > 0) {
while (len == 0) {
mp = mbuf_next(mp);
- if (mp == NULL)
- return (EBADRPC);
+ if (mp == NULL) {
+ error = EBADRPC;
+ goto out;
+ }
mbufcp = NFSMTOD(mp, caddr_t);
len = mbuf_len(mp);
}
@@ -231,6 +235,9 @@ nfsm_mbufuio(struct nfsrv_descript *nd, struct uio *uiop, int siz)
else
nd->nd_dpos += rem;
}
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
#endif /* !APPLE */
@@ -308,9 +315,10 @@ nfsm_dissct(struct nfsrv_descript *nd, int siz)
APPLESTATIC int
nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
{
+ int error = 0;
if (offs == 0)
- return (0);
+ goto out;
/*
* A negative offs should be considered a serious problem.
*/
@@ -330,13 +338,18 @@ nfsm_advance(struct nfsrv_descript *nd, int offs, int left)
while (offs > left) {
offs -= left;
nd->nd_md = mbuf_next(nd->nd_md);
- if (nd->nd_md == NULL)
- return (EBADRPC);
+ if (nd->nd_md == NULL) {
+ error = EBADRPC;
+ goto out;
+ }
left = mbuf_len(nd->nd_md);
nd->nd_dpos = NFSMTOD(nd->nd_md, caddr_t);
}
nd->nd_dpos += offs;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -620,8 +633,10 @@ nfsm_getfh(struct nfsrv_descript *nd, struct nfsfh **nfhpp)
if (nd->nd_flag & (ND_NFSV3 | ND_NFSV4)) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
if ((len = fxdr_unsigned(int, *tl)) <= 0 ||
- len > NFSX_FHMAX)
- return (EBADRPC);
+ len > NFSX_FHMAX) {
+ error = EBADRPC;
+ goto nfsmout;
+ }
} else
len = NFSX_V2FH;
MALLOC(nfhp, struct nfsfh *, sizeof (struct nfsfh) + len,
@@ -629,11 +644,12 @@ nfsm_getfh(struct nfsrv_descript *nd, struct nfsfh **nfhpp)
error = nfsrv_mtostr(nd, nfhp->nfh_fh, len);
if (error) {
FREE((caddr_t)nfhp, M_NFSFH);
- return (error);
+ goto nfsmout;
}
nfhp->nfh_len = len;
*nfhpp = nfhp;
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -660,9 +676,9 @@ nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
aclsize = NFSX_UNSIGNED;
acecnt = fxdr_unsigned(int, *tl);
if (acecnt > ACL_MAX_ENTRIES)
- aceerr = 1;
+ aceerr = NFSERR_ATTRNOTSUPP;
if (nfsrv_useacl == 0)
- aceerr = 1;
+ aceerr = NFSERR_ATTRNOTSUPP;
for (i = 0; i < acecnt; i++) {
if (aclp && !aceerr)
error = nfsrv_dissectace(nd, &aclp->acl_entry[i],
@@ -670,7 +686,7 @@ nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
else
error = nfsrv_skipace(nd, &acesize);
if (error)
- return (error);
+ goto nfsmout;
aclsize += acesize;
}
if (aclp && !aceerr)
@@ -680,6 +696,7 @@ nfsrv_dissectacl(struct nfsrv_descript *nd, NFSACL_T *aclp, int *aclerrp,
if (aclsizep)
*aclsizep = aclsize;
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -697,6 +714,7 @@ nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep)
error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
nfsmout:
*acesizep = NFSM_RNDUP(len) + (4 * NFSX_UNSIGNED);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -715,8 +733,10 @@ nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
cnt = fxdr_unsigned(int, *tl);
- if (cnt < 0)
- return (NFSERR_BADXDR);
+ if (cnt < 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
if (cnt > NFSATTRBIT_MAXWORDS) {
outcnt = NFSATTRBIT_MAXWORDS;
if (retnotsupp)
@@ -735,6 +755,7 @@ nfsrv_getattrbits(struct nfsrv_descript *nd, nfsattrbit_t *attrbitp, int *cntp,
if (cntp)
*cntp = NFSX_UNSIGNED + (cnt * NFSX_UNSIGNED);
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -756,7 +777,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
u_int32_t *leasep, u_int32_t *rderrp, NFSPROC_T *p, struct ucred *cred)
{
u_int32_t *tl;
- int i = 0, j, k, l, m, bitpos, attrsum = 0;
+ int i = 0, j, k, l = 0, m, bitpos, attrsum = 0;
int error, tfhsize, aceerr, attrsize, cnt, retnotsup;
u_char *cp, *cp2, namestr[NFSV4_SMALLSTR + 1];
nfsattrbit_t attrbits, retattrbits, checkattrbits;
@@ -782,7 +803,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
}
if (error)
- return (error);
+ goto nfsmout;
if (compare) {
*retcmpp = retnotsup;
@@ -853,7 +874,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
error = nfsrv_getattrbits(nd, &nap->na_suppattr,
&cnt, &retnotsup);
if (error)
- return (error);
+ goto nfsmout;
if (compare && !(*retcmpp)) {
NFSSETSUPP_ATTRBIT(&checkattrbits);
if (!NFSEQUAL_ATTRBIT(&retattrbits, &checkattrbits)
@@ -1014,9 +1035,10 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
&cnt, p);
if (error) {
acl_free(naclp);
- return (error);
+ goto nfsmout;
}
- if (aceerr || nfsrv_compareacl(aclp, naclp))
+ if (aceerr || aclp == NULL ||
+ nfsrv_compareacl(aclp, naclp))
*retcmpp = NFSERR_NOTSAME;
acl_free(naclp);
} else {
@@ -1033,7 +1055,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
error = nfsrv_dissectacl(nd, NULL, &aceerr,
&cnt, p);
if (error)
- return (error);
+ goto nfsmout;
}
attrsum += cnt;
break;
@@ -1118,7 +1140,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
case NFSATTRBIT_FILEHANDLE:
error = nfsm_getfh(nd, &tnfhp);
if (error)
- return (error);
+ goto nfsmout;
tfhsize = tnfhp->nfh_len;
if (compare) {
if (!(*retcmpp) &&
@@ -1184,7 +1206,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
case NFSATTRBIT_FSLOCATIONS:
error = nfsrv_getrefstr(nd, &cp, &cp2, &l, &m);
if (error)
- return (error);
+ goto nfsmout;
attrsum += l;
if (compare && !(*retcmpp)) {
refp = nfsv4root_getreferral(vp, NULL, 0);
@@ -1360,8 +1382,10 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
case NFSATTRBIT_OWNER:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
j = fxdr_unsigned(int, *tl);
- if (j < 0)
- return (NFSERR_BADXDR);
+ if (j < 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
if (j > NFSV4_SMALLSTR)
cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
@@ -1371,7 +1395,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
if (error) {
if (j > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
- return (error);
+ goto nfsmout;
}
if (compare) {
if (!(*retcmpp)) {
@@ -1391,8 +1415,10 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
case NFSATTRBIT_OWNERGROUP:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
j = fxdr_unsigned(int, *tl);
- if (j < 0)
- return (NFSERR_BADXDR);
+ if (j < 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
attrsum += (NFSX_UNSIGNED + NFSM_RNDUP(j));
if (j > NFSV4_SMALLSTR)
cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
@@ -1402,7 +1428,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
if (error) {
if (j > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
- return (error);
+ goto nfsmout;
}
if (compare) {
if (!(*retcmpp)) {
@@ -1708,6 +1734,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
error = nfsm_advance(nd, attrsize - attrsum, -1);
}
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1904,8 +1931,10 @@ nfsrv_mtostr(struct nfsrv_descript *nd, char *str, int siz)
siz -= xfer;
if (siz > 0) {
mp = mbuf_next(mp);
- if (mp == NULL)
- return (EBADRPC);
+ if (mp == NULL) {
+ error = EBADRPC;
+ goto out;
+ }
cp = NFSMTOD(mp, caddr_t);
len = mbuf_len(mp);
} else {
@@ -1922,6 +1951,9 @@ nfsrv_mtostr(struct nfsrv_descript *nd, char *str, int siz)
else
nd->nd_dpos += rem;
}
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1995,12 +2027,12 @@ nfsv4_fillattr(struct nfsrv_descript *nd, struct mount *mp, vnode_t vp,
supports_nfsv4acls == 0)) {
NFSCLRBIT_ATTRBIT(retbitp, NFSATTRBIT_ACL);
} else if (naclp != NULL) {
- if (vn_lock(vp, LK_SHARED) == 0) {
+ if (NFSVOPLOCK(vp, LK_SHARED) == 0) {
error = VOP_ACCESSX(vp, VREAD_ACL, cred, p);
if (error == 0)
error = VOP_GETACL(vp, ACL_TYPE_NFS4,
naclp, cred, p);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
} else
error = NFSERR_PERM;
if (error != 0) {
@@ -2568,9 +2600,12 @@ nfsv4_strtouid(u_char *str, int len, uid_t *uidp, NFSPROC_T *p)
u_char *cp;
struct nfsusrgrp *usrp;
int cnt, ret;
+ int error = 0;
- if (len == 0)
- return (NFSERR_BADOWNER);
+ if (len == 0) {
+ error = NFSERR_BADOWNER;
+ goto out;
+ }
/*
* Look for an '@'.
*/
@@ -2601,7 +2636,8 @@ tryagain:
if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
*uidp = nfsrv_defaultuid;
NFSUNLOCKNAMEID();
- return (0);
+ error = 0;
+ goto out;
}
LIST_FOREACH(usrp, NFSUSERNAMEHASH(str, len), lug_namehash) {
@@ -2613,7 +2649,8 @@ tryagain:
TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
NFSUNLOCKNAMEID();
- return (0);
+ error = 0;
+ goto out;
}
}
NFSUNLOCKNAMEID();
@@ -2622,7 +2659,11 @@ tryagain:
str, p);
if (ret == 0 && cnt < 2)
goto tryagain;
- return (NFSERR_BADOWNER);
+ error = NFSERR_BADOWNER;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -2748,9 +2789,12 @@ nfsv4_strtogid(u_char *str, int len, gid_t *gidp, NFSPROC_T *p)
u_char *cp;
struct nfsusrgrp *usrp;
int cnt, ret;
+ int error = 0;
- if (len == 0)
- return (NFSERR_BADOWNER);
+ if (len == 0) {
+ error = NFSERR_BADOWNER;
+ goto out;
+ }
/*
* Look for an '@'.
*/
@@ -2779,7 +2823,8 @@ tryagain:
if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
*gidp = nfsrv_defaultgid;
NFSUNLOCKNAMEID();
- return (0);
+ error = 0;
+ goto out;
}
LIST_FOREACH(usrp, NFSGROUPNAMEHASH(str, len), lug_namehash) {
@@ -2791,7 +2836,8 @@ tryagain:
TAILQ_REMOVE(&nfsuserlruhead, usrp, lug_lru);
TAILQ_INSERT_TAIL(&nfsuserlruhead, usrp, lug_lru);
NFSUNLOCKNAMEID();
- return (0);
+ error = 0;
+ goto out;
}
}
NFSUNLOCKNAMEID();
@@ -2800,7 +2846,11 @@ tryagain:
str, p);
if (ret == 0 && cnt < 2)
goto tryagain;
- return (NFSERR_BADOWNER);
+ error = NFSERR_BADOWNER;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -2845,7 +2895,8 @@ nfsrv_nfsuserdport(u_short port, NFSPROC_T *p)
NFSLOCKNAMEID();
if (nfsrv_nfsuserd) {
NFSUNLOCKNAMEID();
- return (EPERM);
+ error = EPERM;
+ goto out;
}
nfsrv_nfsuserd = 1;
NFSUNLOCKNAMEID();
@@ -2871,6 +2922,8 @@ nfsrv_nfsuserdport(u_short port, NFSPROC_T *p)
NFSSOCKADDRFREE(rp->nr_nam);
nfsrv_nfsuserd = 0;
}
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -2910,7 +2963,8 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p)
NFSLOCKNAMEID();
if (nfsrv_nfsuserd == 0) {
NFSUNLOCKNAMEID();
- return (EPERM);
+ error = EPERM;
+ goto out;
}
NFSUNLOCKNAMEID();
nd = &nfsd;
@@ -2936,6 +2990,8 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name, NFSPROC_T *p)
mbuf_freem(nd->nd_mrep);
error = nd->nd_repstat;
}
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -2992,7 +3048,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
NFSUNLOCKNAMEID();
if (error)
free(cp, M_NFSSTRING);
- return (error);
+ goto out;
}
/*
@@ -3005,7 +3061,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
nidp->nid_namelen);
if (error) {
free((caddr_t)newusrp, M_NFSUSERGROUP);
- return (error);
+ goto out;
}
newusrp->lug_namelen = nidp->nid_namelen;
@@ -3080,6 +3136,8 @@ nfssvc_idname(struct nfsd_idargs *nidp)
} else
FREE((caddr_t)newusrp, M_NFSUSERGROUP);
NFSUNLOCKNAMEID();
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -3109,6 +3167,7 @@ nfsrv_checkutf8(u_int8_t *cp, int len)
int cnt = 0, gotd = 0, shift = 0;
u_int8_t byte;
static int utf8_shift[5] = { 7, 11, 16, 21, 26 };
+ int error = 0;
/*
* Here are what the variables are used for:
@@ -3125,14 +3184,18 @@ nfsrv_checkutf8(u_int8_t *cp, int len)
if (cnt > 0) {
/* This handles the 10xxxxxx bytes */
if ((*cp & 0xc0) != 0x80 ||
- (gotd && (*cp & 0x20)))
- return (NFSERR_INVAL);
+ (gotd && (*cp & 0x20))) {
+ error = NFSERR_INVAL;
+ goto out;
+ }
gotd = 0;
val <<= 6;
val |= (*cp & 0x3f);
cnt--;
- if (cnt == 0 && (val >> shift) == 0x0)
- return (NFSERR_INVAL);
+ if (cnt == 0 && (val >> shift) == 0x0) {
+ error = NFSERR_INVAL;
+ goto out;
+ }
} else if (*cp & 0x80) {
/* first byte of multi byte char */
byte = *cp;
@@ -3140,8 +3203,10 @@ nfsrv_checkutf8(u_int8_t *cp, int len)
cnt++;
byte <<= 1;
}
- if (cnt == 0 || cnt == 6)
- return (NFSERR_INVAL);
+ if (cnt == 0 || cnt == 6) {
+ error = NFSERR_INVAL;
+ goto out;
+ }
val = (*cp & (0x3f >> cnt));
shift = utf8_shift[cnt - 1];
if (cnt == 2 && val == 0xd)
@@ -3152,8 +3217,11 @@ nfsrv_checkutf8(u_int8_t *cp, int len)
len--;
}
if (cnt > 0)
- return (NFSERR_INVAL);
- return (0);
+ error = NFSERR_INVAL;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -3174,7 +3242,7 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
{
u_int32_t *tl;
u_char *cp = NULL, *cp2 = NULL, *cp3, *str;
- int i, j, len, stringlen, cnt, slen, siz, xdrsum, error, nsrv;
+ int i, j, len, stringlen, cnt, slen, siz, xdrsum, error = 0, nsrv;
struct list {
SLIST_ENTRY(list) next;
int len;
@@ -3192,15 +3260,20 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
*/
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
len = fxdr_unsigned(int, *tl);
- if (len < 0 || len > 10240)
- return (NFSERR_BADXDR);
+ if (len < 0 || len > 10240) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
if (len == 0) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- if (*tl != 0)
- return (NFSERR_BADXDR);
+ if (*tl != 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
*nilp = 1;
*sump = 2 * NFSX_UNSIGNED;
- return (0);
+ error = 0;
+ goto nfsmout;
}
cp = malloc(len + 1, M_NFSSTRING, M_WAITOK);
error = nfsrv_mtostr(nd, cp, len);
@@ -3210,10 +3283,8 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
if (cnt <= 0)
error = NFSERR_BADXDR;
}
- if (error) {
- free(cp, M_NFSSTRING);
- return (error);
- }
+ if (error)
+ goto nfsmout;
/*
* Now, loop through the location list and make up the srvlist.
@@ -3227,9 +3298,8 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nsrv = fxdr_unsigned(int, *tl);
if (nsrv <= 0) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (NFSERR_BADXDR);
+ error = NFSERR_BADXDR;
+ goto nfsmout;
}
/*
@@ -3238,9 +3308,8 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
len = fxdr_unsigned(int, *tl);
if (len <= 0 || len > 1024) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (NFSERR_BADXDR);
+ error = NFSERR_BADXDR;
+ goto nfsmout;
}
nfsrv_refstrbigenough(siz + len + 3, &cp2, &cp3, &slen);
if (cp3 != cp2) {
@@ -3248,11 +3317,8 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
siz++;
}
error = nfsrv_mtostr(nd, cp3, len);
- if (error) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (error);
- }
+ if (error)
+ goto nfsmout;
cp3 += len;
*cp3++ = ':';
siz += (len + 1);
@@ -3264,18 +3330,14 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
len = fxdr_unsigned(int, *tl);
if (len <= 0 || len > 1024) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (NFSERR_BADXDR);
+ error = NFSERR_BADXDR;
+ goto nfsmout;
}
lsp = (struct list *)malloc(sizeof (struct list)
+ len, M_TEMP, M_WAITOK);
error = nfsrv_mtostr(nd, lsp->host, len);
- if (error) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (error);
- }
+ if (error)
+ goto nfsmout;
xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
lsp->len = len;
SLIST_INSERT_HEAD(&head, lsp, next);
@@ -3287,17 +3349,13 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
len = fxdr_unsigned(int, *tl);
if (len <= 0 || len > 1024) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (NFSERR_BADXDR);
+ error = NFSERR_BADXDR;
+ goto nfsmout;
}
nfsrv_refstrbigenough(siz + len + 1, &cp2, &cp3, &slen);
error = nfsrv_mtostr(nd, cp3, len);
- if (error) {
- free(cp, M_NFSSTRING);
- free(cp2, M_NFSSTRING);
- return (error);
- }
+ if (error)
+ goto nfsmout;
xdrsum += NFSX_UNSIGNED + NFSM_RNDUP(len);
str = cp3;
stringlen = len;
@@ -3320,12 +3378,14 @@ nfsrv_getrefstr(struct nfsrv_descript *nd, u_char **fsrootp, u_char **srvp,
*fsrootp = cp;
*srvp = cp2;
*sump = xdrsum;
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
if (cp != NULL)
free(cp, M_NFSSTRING);
if (cp2 != NULL)
free(cp2, M_NFSSTRING);
+ NFSEXITCODE2(error, nd);
return (error);
}
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 5f944b5..f095641 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -325,6 +325,8 @@ struct ucred *newnfs_getcred(void);
void newnfs_setroot(struct ucred *);
int nfs_catnap(int, int, const char *);
struct nfsreferral *nfsv4root_getreferral(vnode_t, vnode_t, u_int32_t);
+int nfsvno_pathconf(vnode_t, int, register_t *, struct ucred *,
+ NFSPROC_T *);
int nfsrv_atroot(vnode_t, long *);
void newnfs_timer(void *);
int nfs_supportsnfsv4acls(vnode_t);
@@ -438,6 +440,7 @@ int nfscl_getcl(vnode_t, struct ucred *, NFSPROC_T *,
struct nfsclclient *nfscl_findcl(struct nfsmount *);
void nfscl_clientrelease(struct nfsclclient *);
void nfscl_freelock(struct nfscllock *, int);
+void nfscl_freelockowner(struct nfscllockowner *, int);
int nfscl_getbytelock(vnode_t, u_int64_t, u_int64_t, short,
struct ucred *, NFSPROC_T *, struct nfsclclient *, int, void *, int,
u_int8_t *, u_int8_t *, struct nfscllockowner **, int *, int *);
@@ -568,8 +571,6 @@ int nfsvno_checkexp(mount_t, NFSSOCKADDR_T, struct nfsexstuff *,
struct ucred **);
int nfsvno_fhtovp(mount_t, fhandle_t *, NFSSOCKADDR_T, int,
vnode_t *, struct nfsexstuff *, struct ucred **);
-int nfsvno_pathconf(vnode_t, int, register_t *, struct ucred *,
- NFSPROC_T *);
vnode_t nfsvno_getvp(fhandle_t *);
int nfsvno_advlock(vnode_t, int, u_int64_t, u_int64_t, NFSPROC_T *);
int nfsrv_v4rootexport(void *, struct ucred *, NFSPROC_T *);
diff --git a/sys/fs/nfs/nfsdport.h b/sys/fs/nfs/nfsdport.h
index a3f05db..529ada2 100644
--- a/sys/fs/nfs/nfsdport.h
+++ b/sys/fs/nfs/nfsdport.h
@@ -57,6 +57,22 @@ struct nfsexstuff {
int nes_secflavors[MAXSECFLAVORS]; /* and the flavors */
};
+/*
+ * These are NO-OPS for BSD until Isilon upstreams EXITCODE support.
+ * EXITCODE is an in-memory ring buffer that holds the routines failing status.
+ * This is a valuable tool to use when debugging and analyzing issues.
+ * In addition to recording a routine's failing status, it offers
+ * logging of routines for call stack tracing.
+ * EXITCODE should be used only in routines that return a true errno value, as
+ * that value will be formatted to a displayable errno string. Routines that
+ * return regular int status that are not true errno should not set EXITCODE.
+ * If you want to log routine tracing, you can add EXITCODE(0) to any routine.
+ * NFS extended the EXITCODE with EXITCODE2 to record either the routine's
+ * exit errno status or the nd_repstat.
+ */
+#define NFSEXITCODE(error)
+#define NFSEXITCODE2(error, nd)
+
#define NFSVNO_EXINIT(e) ((e)->nes_exflag = 0)
#define NFSVNO_EXPORTED(e) ((e)->nes_exflag & MNT_EXPORTED)
#define NFSVNO_EXRDONLY(e) ((e)->nes_exflag & MNT_EXRDONLY)
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index c21482d..726d3b5 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -267,6 +267,7 @@
* NFS_V3NPROCS is one greater than the last V3 op and NFS_NPROCS is
* one greater than the last number.
*/
+#ifndef NFS_V3NPROCS
#define NFS_V3NPROCS 22
#define NFSPROC_LOOKUPP 22
@@ -293,6 +294,7 @@
* Must be defined as one higher than the last Proc# above.
*/
#define NFSV4_NPROCS 41
+#endif /* NFS_V3NPROCS */
/*
* Stats structure
@@ -358,7 +360,9 @@ struct ext_nfsstats {
/*
* Define NFS_NPROCS as NFSV4_NPROCS for the experimental kernel code.
*/
+#ifndef NFS_NPROCS
#define NFS_NPROCS NFSV4_NPROCS
+#endif
#include <fs/nfs/nfskpiport.h>
#include <fs/nfs/nfsdport.h>
@@ -832,10 +836,13 @@ void nfsd_mntinit(void);
/*
* Define these for vnode lock/unlock ops.
+ *
+ * These are good abstractions to macro out, so that they can be added to
+ * later, for debugging or stats, etc.
*/
-#define NFSVOPLOCK(v, f, p) vn_lock((v), (f))
-#define NFSVOPUNLOCK(v, f, p) VOP_UNLOCK((v), (f))
-#define NFSVOPISLOCKED(v, p) VOP_ISLOCKED((v))
+#define NFSVOPLOCK(v, f) vn_lock((v), (f))
+#define NFSVOPUNLOCK(v, f) VOP_UNLOCK((v), (f))
+#define NFSVOPISLOCKED(v) VOP_ISLOCKED((v))
/*
* Define ncl_hash().
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index 6b66c1f..5ae2e3d 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -226,6 +226,48 @@
#define NFSPROC_COMMIT 21
/*
+ * The lower numbers -> 21 are used by NFSv2 and v3. These define higher
+ * numbers used by NFSv4.
+ * NFS_V3NPROCS is one greater than the last V3 op and NFS_NPROCS is
+ * one greater than the last number.
+ */
+#ifndef NFS_V3NPROCS
+#define NFS_V3NPROCS 22
+
+#define NFSPROC_LOOKUPP 22
+#define NFSPROC_SETCLIENTID 23
+#define NFSPROC_SETCLIENTIDCFRM 24
+#define NFSPROC_LOCK 25
+#define NFSPROC_LOCKU 26
+#define NFSPROC_OPEN 27
+#define NFSPROC_CLOSE 28
+#define NFSPROC_OPENCONFIRM 29
+#define NFSPROC_LOCKT 30
+#define NFSPROC_OPENDOWNGRADE 31
+#define NFSPROC_RENEW 32
+#define NFSPROC_PUTROOTFH 33
+#define NFSPROC_RELEASELCKOWN 34
+#define NFSPROC_DELEGRETURN 35
+#define NFSPROC_RETDELEGREMOVE 36
+#define NFSPROC_RETDELEGRENAME1 37
+#define NFSPROC_RETDELEGRENAME2 38
+#define NFSPROC_GETACL 39
+#define NFSPROC_SETACL 40
+
+/*
+ * Must be defined as one higher than the last Proc# above.
+ */
+#define NFSV4_NPROCS 41
+#endif /* NFS_V3NPROCS */
+
+/*
+ * Define NFS_NPROCS as NFSV4_NPROCS for the experimental kernel code.
+ */
+#ifndef NFS_NPROCS
+#define NFS_NPROCS NFSV4_NPROCS
+#endif
+
+/*
* NFSPROC_NOOP is a fake op# that can't be the same as any V2/3/4 Procedure
* or Operation#. Since the NFS V4 Op #s go higher, use NFSV4OP_NOPS, which
* is one greater than the highest Op#.
@@ -826,15 +868,24 @@ struct nfsv3_sattr {
* NFSATTRBIT_WRITEGETATTR0 - bits 0<->31
*/
#define NFSATTRBIT_WRITEGETATTR0 \
- (NFSATTRBM_CHANGE | \
+ (NFSATTRBM_SUPPORTEDATTRS | \
+ NFSATTRBM_TYPE | \
+ NFSATTRBM_CHANGE | \
NFSATTRBM_SIZE | \
- NFSATTRBM_FSID)
+ NFSATTRBM_FSID | \
+ NFSATTRBM_FILEID | \
+ NFSATTRBM_MAXREAD)
/*
* NFSATTRBIT_WRITEGETATTR1 - bits 32<->63
*/
#define NFSATTRBIT_WRITEGETATTR1 \
- (NFSATTRBM_TIMEMETADATA | \
+ (NFSATTRBM_MODE | \
+ NFSATTRBM_NUMLINKS | \
+ NFSATTRBM_RAWDEV | \
+ NFSATTRBM_SPACEUSED | \
+ NFSATTRBM_TIMEACCESS | \
+ NFSATTRBM_TIMEMETADATA | \
NFSATTRBM_TIMEMODIFY)
/*
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index 95138ec..b33c8a5 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
@@ -55,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <fs/nfsclient/nfsmount.h>
#include <fs/nfsclient/nfs.h>
#include <fs/nfsclient/nfsnode.h>
+#include <fs/nfsclient/nfs_kdtrace.h>
extern int newnfs_directio_allow_mmap;
extern struct nfsstats newnfsstats;
@@ -399,6 +402,7 @@ nfs_bioread_check_cons(struct vnode *vp, struct thread *td, struct ucred *cred)
goto out;
}
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = VOP_GETATTR(vp, &vattr, cred);
if (error)
goto out;
@@ -915,6 +919,7 @@ ncl_write(struct vop_write_args *ap)
#endif
flush_and_restart:
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
if (error)
return (error);
@@ -928,6 +933,7 @@ flush_and_restart:
*/
if (ioflag & IO_APPEND) {
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = VOP_GETATTR(vp, &vattr, cred);
if (error)
return (error);
@@ -1748,6 +1754,7 @@ ncl_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td,
mtx_lock(&np->n_mtx);
np->n_flag |= NWRITEERR;
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
mtx_unlock(&np->n_mtx);
}
bp->b_dirtyoff = bp->b_dirtyend = 0;
diff --git a/sys/fs/nfsclient/nfs_clkdtrace.c b/sys/fs/nfsclient/nfs_clkdtrace.c
new file mode 100644
index 0000000..c7db3a4
--- /dev/null
+++ b/sys/fs/nfsclient/nfs_clkdtrace.c
@@ -0,0 +1,600 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <sys/dtrace.h>
+#include <sys/dtrace_bsd.h>
+
+#include <fs/nfs/nfsproto.h>
+
+#include <fs/nfsclient/nfs_kdtrace.h>
+
+/*
+ * dtnfscl is a DTrace provider that tracks the intent to perform RPCs
+ * in the NFS client, as well as acess to and maintenance of the access and
+ * attribute caches. This is not quite the same as RPCs, because NFS may
+ * issue multiple RPC transactions in the event that authentication fails,
+ * there's a jukebox error, or none at all if the access or attribute cache
+ * hits. However, it cleanly represents the logical layer between RPC
+ * transmission and vnode/vfs operations, providing access to state linking
+ * the two.
+ */
+
+static int dtnfsclient_unload(void);
+static void dtnfsclient_getargdesc(void *, dtrace_id_t, void *,
+ dtrace_argdesc_t *);
+static void dtnfsclient_provide(void *, dtrace_probedesc_t *);
+static void dtnfsclient_destroy(void *, dtrace_id_t, void *);
+static void dtnfsclient_enable(void *, dtrace_id_t, void *);
+static void dtnfsclient_disable(void *, dtrace_id_t, void *);
+static void dtnfsclient_load(void *);
+
+static dtrace_pattr_t dtnfsclient_attr = {
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+};
+
+/*
+ * Description of NFSv4, NFSv3 and (optional) NFSv2 probes for a procedure.
+ */
+struct dtnfsclient_rpc {
+ char *nr_v4_name;
+ char *nr_v3_name; /* Or NULL if none. */
+ char *nr_v2_name; /* Or NULL if none. */
+
+ /*
+ * IDs for the start and done cases, for NFSv2, NFSv3 and NFSv4.
+ */
+ uint32_t nr_v2_id_start, nr_v2_id_done;
+ uint32_t nr_v3_id_start, nr_v3_id_done;
+ uint32_t nr_v4_id_start, nr_v4_id_done;
+};
+
+/*
+ * This table is indexed by NFSv3 procedure number, but also used for NFSv2
+ * procedure names and NFSv4 operations.
+ */
+static struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS + 1] = {
+ { "null", "null", "null" },
+ { "getattr", "getattr", "getattr" },
+ { "setattr", "setattr", "setattr" },
+ { "lookup", "lookup", "lookup" },
+ { "access", "access", "noop" },
+ { "readlink", "readlink", "readlink" },
+ { "read", "read", "read" },
+ { "write", "write", "write" },
+ { "create", "create", "create" },
+ { "mkdir", "mkdir", "mkdir" },
+ { "symlink", "symlink", "symlink" },
+ { "mknod", "mknod" },
+ { "remove", "remove", "remove" },
+ { "rmdir", "rmdir", "rmdir" },
+ { "rename", "rename", "rename" },
+ { "link", "link", "link" },
+ { "readdir", "readdir", "readdir" },
+ { "readdirplus", "readdirplus" },
+ { "fsstat", "fsstat", "statfs" },
+ { "fsinfo", "fsinfo" },
+ { "pathconf", "pathconf" },
+ { "commit", "commit" },
+ { "lookupp" },
+ { "setclientid" },
+ { "setclientidcfrm" },
+ { "lock" },
+ { "locku" },
+ { "open" },
+ { "close" },
+ { "openconfirm" },
+ { "lockt" },
+ { "opendowngrade" },
+ { "renew" },
+ { "putrootfh" },
+ { "releaselckown" },
+ { "delegreturn" },
+ { "retdelegremove" },
+ { "retdelegrename1" },
+ { "retdelegrename2" },
+ { "getacl" },
+ { "setacl" },
+ { "noop", "noop", "noop" }
+};
+
+/*
+ * Module name strings.
+ */
+static char *dtnfsclient_accesscache_str = "accesscache";
+static char *dtnfsclient_attrcache_str = "attrcache";
+static char *dtnfsclient_nfs2_str = "nfs2";
+static char *dtnfsclient_nfs3_str = "nfs3";
+static char *dtnfsclient_nfs4_str = "nfs4";
+
+/*
+ * Function name strings.
+ */
+static char *dtnfsclient_flush_str = "flush";
+static char *dtnfsclient_load_str = "load";
+static char *dtnfsclient_get_str = "get";
+
+/*
+ * Name strings.
+ */
+static char *dtnfsclient_done_str = "done";
+static char *dtnfsclient_hit_str = "hit";
+static char *dtnfsclient_miss_str = "miss";
+static char *dtnfsclient_start_str = "start";
+
+static dtrace_pops_t dtnfsclient_pops = {
+ dtnfsclient_provide,
+ NULL,
+ dtnfsclient_enable,
+ dtnfsclient_disable,
+ NULL,
+ NULL,
+ dtnfsclient_getargdesc,
+ NULL,
+ NULL,
+ dtnfsclient_destroy
+};
+
+static dtrace_provider_id_t dtnfsclient_id;
+
+/*
+ * Most probes are generated from the above RPC table, but for access and
+ * attribute caches, we have specific IDs we recognize and handle specially
+ * in various spots.
+ */
+extern uint32_t nfscl_accesscache_flush_done_id;
+extern uint32_t nfscl_accesscache_get_hit_id;
+extern uint32_t nfscl_accesscache_get_miss_id;
+extern uint32_t nfscl_accesscache_load_done_id;
+
+extern uint32_t nfscl_attrcache_flush_done_id;
+extern uint32_t nfscl_attrcache_get_hit_id;
+extern uint32_t nfscl_attrcache_get_miss_id;
+extern uint32_t nfscl_attrcache_load_done_id;
+
+/*
+ * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
+ * stored in one of these two NFS client-allocated arrays; 0 indicates that
+ * the event is not being traced so probes should not be called.
+ *
+ * For simplicity, we allocate both v2, v3 and v4 arrays as NFS_NPROCS + 1, and
+ * the v2, v3 arrays are simply sparse.
+ */
+extern uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1];
+extern uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1];
+
+extern uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1];
+extern uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1];
+
+extern uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1];
+extern uint32_t nfscl_nfs4_done_probes[NFS_NPROCS + 1];
+
+/*
+ * Look up a DTrace probe ID to see if it's associated with a "done" event --
+ * if so, we will return a fourth argument type of "int".
+ */
+static int
+dtnfs234_isdoneprobe(dtrace_id_t id)
+{
+ int i;
+
+ for (i = 0; i < NFS_NPROCS + 1; i++) {
+ if (dtnfsclient_rpcs[i].nr_v4_id_done == id ||
+ dtnfsclient_rpcs[i].nr_v3_id_done == id ||
+ dtnfsclient_rpcs[i].nr_v2_id_done == id)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
+ dtrace_argdesc_t *desc)
+{
+ const char *p = NULL;
+
+ if (id == nfscl_accesscache_flush_done_id ||
+ id == nfscl_attrcache_flush_done_id ||
+ id == nfscl_attrcache_get_miss_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfscl_accesscache_get_hit_id ||
+ id == nfscl_accesscache_get_miss_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfscl_accesscache_load_done_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfscl_attrcache_get_hit_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct vattr *";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfscl_attrcache_load_done_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct vattr *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct mbuf *";
+ break;
+ case 2:
+ p = "struct ucred *";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ if (dtnfs234_isdoneprobe(id)) {
+ p = "int";
+ break;
+ }
+ /* FALLSTHROUGH */
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ }
+ if (p != NULL)
+ strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
+}
+
+static void
+dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
+{
+ int i;
+
+ if (desc != NULL)
+ return;
+
+ /*
+ * Register access cache probes.
+ */
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
+ nfscl_accesscache_flush_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
+ nfscl_accesscache_get_hit_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
+ nfscl_accesscache_get_miss_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
+ nfscl_accesscache_load_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
+ }
+
+ /*
+ * Register attribute cache probes.
+ */
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
+ nfscl_attrcache_flush_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
+ nfscl_attrcache_get_hit_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
+ nfscl_attrcache_get_miss_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
+ nfscl_attrcache_load_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
+ }
+
+ /*
+ * Register NFSv2 RPC procedures; note sparseness check for each slot
+ * in the NFSv3, NFSv4 procnum-indexed array.
+ */
+ for (i = 0; i < NFS_NPROCS + 1; i++) {
+ if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v2_id_start =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name,
+ dtnfsclient_start_str, 0,
+ &nfscl_nfs2_start_probes[i]);
+ }
+ if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v2_id_done =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name,
+ dtnfsclient_done_str, 0,
+ &nfscl_nfs2_done_probes[i]);
+ }
+ }
+
+ /*
+ * Register NFSv3 RPC procedures; note sparseness check for each slot
+ * in the NFSv4 procnum-indexed array.
+ */
+ for (i = 0; i < NFS_NPROCS + 1; i++) {
+ if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v3_id_start =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name,
+ dtnfsclient_start_str, 0,
+ &nfscl_nfs3_start_probes[i]);
+ }
+ if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v3_id_done =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name,
+ dtnfsclient_done_str, 0,
+ &nfscl_nfs3_done_probes[i]);
+ }
+ }
+
+ /*
+ * Register NFSv4 RPC procedures.
+ */
+ for (i = 0; i < NFS_NPROCS + 1; i++) {
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
+ dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v4_id_start =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs4_str,
+ dtnfsclient_rpcs[i].nr_v4_name,
+ dtnfsclient_start_str, 0,
+ &nfscl_nfs4_start_probes[i]);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
+ dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_done_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v4_id_done =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs4_str,
+ dtnfsclient_rpcs[i].nr_v4_name,
+ dtnfsclient_done_str, 0,
+ &nfscl_nfs4_done_probes[i]);
+ }
+ }
+}
+
+static void
+dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
+{
+}
+
+static void
+dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
+{
+ uint32_t *p = parg;
+ void *f = dtrace_probe;
+
+ if (id == nfscl_accesscache_flush_done_id)
+ dtrace_nfscl_accesscache_flush_done_probe = f;
+ else if (id == nfscl_accesscache_get_hit_id)
+ dtrace_nfscl_accesscache_get_hit_probe = f;
+ else if (id == nfscl_accesscache_get_miss_id)
+ dtrace_nfscl_accesscache_get_miss_probe = f;
+ else if (id == nfscl_accesscache_load_done_id)
+ dtrace_nfscl_accesscache_load_done_probe = f;
+ else if (id == nfscl_attrcache_flush_done_id)
+ dtrace_nfscl_attrcache_flush_done_probe = f;
+ else if (id == nfscl_attrcache_get_hit_id)
+ dtrace_nfscl_attrcache_get_hit_probe = f;
+ else if (id == nfscl_attrcache_get_miss_id)
+ dtrace_nfscl_attrcache_get_miss_probe = f;
+ else if (id == nfscl_attrcache_load_done_id)
+ dtrace_nfscl_attrcache_load_done_probe = f;
+ else
+ *p = id;
+}
+
+static void
+dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
+{
+ uint32_t *p = parg;
+
+ if (id == nfscl_accesscache_flush_done_id)
+ dtrace_nfscl_accesscache_flush_done_probe = NULL;
+ else if (id == nfscl_accesscache_get_hit_id)
+ dtrace_nfscl_accesscache_get_hit_probe = NULL;
+ else if (id == nfscl_accesscache_get_miss_id)
+ dtrace_nfscl_accesscache_get_miss_probe = NULL;
+ else if (id == nfscl_accesscache_load_done_id)
+ dtrace_nfscl_accesscache_load_done_probe = NULL;
+ else if (id == nfscl_attrcache_flush_done_id)
+ dtrace_nfscl_attrcache_flush_done_probe = NULL;
+ else if (id == nfscl_attrcache_get_hit_id)
+ dtrace_nfscl_attrcache_get_hit_probe = NULL;
+ else if (id == nfscl_attrcache_get_miss_id)
+ dtrace_nfscl_attrcache_get_miss_probe = NULL;
+ else if (id == nfscl_attrcache_load_done_id)
+ dtrace_nfscl_attrcache_load_done_probe = NULL;
+ else
+ *p = 0;
+}
+
+static void
+dtnfsclient_load(void *dummy)
+{
+
+ if (dtrace_register("nfscl", &dtnfsclient_attr,
+ DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
+ &dtnfsclient_id) != 0)
+ return;
+
+ dtrace_nfscl_nfs234_start_probe =
+ (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
+ dtrace_nfscl_nfs234_done_probe =
+ (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
+}
+
+
+static int
+dtnfsclient_unload()
+{
+
+ dtrace_nfscl_nfs234_start_probe = NULL;
+ dtrace_nfscl_nfs234_done_probe = NULL;
+
+ return (dtrace_unregister(dtnfsclient_id));
+}
+
+static int
+dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ break;
+
+ case MOD_UNLOAD:
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
+}
+
+SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ dtnfsclient_load, NULL);
+SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ dtnfsclient_unload, NULL);
+
+DEV_MODULE(dtnfscl, dtnfsclient_modevent, NULL);
+MODULE_VERSION(dtnfscl, 1);
+MODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1);
+MODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1);
+MODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1);
+MODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1);
diff --git a/sys/fs/nfsclient/nfs_clkrpc.c b/sys/fs/nfsclient/nfs_clkrpc.c
index c4f7e94..0cd41b3 100644
--- a/sys/fs/nfsclient/nfs_clkrpc.c
+++ b/sys/fs/nfsclient/nfs_clkrpc.c
@@ -215,12 +215,9 @@ nfscbd_addsock(struct file *fp)
int
nfscbd_nfsd(struct thread *td, struct nfsd_nfscbd_args *args)
{
-#ifdef KGSSAPI
char principal[128];
int error;
-#endif
-#ifdef KGSSAPI
if (args != NULL) {
error = copyinstr(args->principal, principal,
sizeof(principal), NULL);
@@ -229,7 +226,6 @@ nfscbd_nfsd(struct thread *td, struct nfsd_nfscbd_args *args)
} else {
principal[0] = '\0';
}
-#endif
/*
* Only the first nfsd actually does any work. The RPC code
@@ -244,20 +240,16 @@ nfscbd_nfsd(struct thread *td, struct nfsd_nfscbd_args *args)
NFSD_UNLOCK();
-#ifdef KGSSAPI
if (principal[0] != '\0')
- rpc_gss_set_svc_name(principal, "kerberosv5",
+ rpc_gss_set_svc_name_call(principal, "kerberosv5",
GSS_C_INDEFINITE, NFS_CALLBCKPROG, NFSV4_CBVERS);
-#endif
nfscbd_pool->sp_minthreads = 4;
nfscbd_pool->sp_maxthreads = 4;
svc_run(nfscbd_pool);
-#ifdef KGSSAPI
- rpc_gss_clear_svc_name(NFS_CALLBCKPROG, NFSV4_CBVERS);
-#endif
+ rpc_gss_clear_svc_name_call(NFS_CALLBCKPROG, NFSV4_CBVERS);
NFSD_LOCK();
nfs_numnfscbd--;
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c
index d4d652e..d15de6e 100644
--- a/sys/fs/nfsclient/nfs_clnode.c
+++ b/sys/fs/nfsclient/nfs_clnode.c
@@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
@@ -53,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <fs/nfsclient/nfsnode.h>
#include <fs/nfsclient/nfsmount.h>
#include <fs/nfsclient/nfs.h>
+#include <fs/nfsclient/nfs_kdtrace.h>
#include <nfs/nfs_lock.h>
@@ -300,7 +303,9 @@ ncl_invalcaches(struct vnode *vp)
mtx_lock(&np->n_mtx);
for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
np->n_accesscache[i].stamp = 0;
+ KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
mtx_unlock(&np->n_mtx);
}
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 4d88bd2..44d3c74 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -34,6 +34,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+
/*
* generally, I don't like #includes inside .h files, but it seems to
* be the easiest way to handle the port.
@@ -43,6 +45,26 @@ __FBSDID("$FreeBSD$");
#include <netinet/if_ether.h>
#include <net/if_types.h>
+#include <fs/nfsclient/nfs_kdtrace.h>
+
+#ifdef KDTRACE_HOOKS
+dtrace_nfsclient_attrcache_flush_probe_func_t
+ dtrace_nfscl_attrcache_flush_done_probe;
+uint32_t nfscl_attrcache_flush_done_id;
+
+dtrace_nfsclient_attrcache_get_hit_probe_func_t
+ dtrace_nfscl_attrcache_get_hit_probe;
+uint32_t nfscl_attrcache_get_hit_id;
+
+dtrace_nfsclient_attrcache_get_miss_probe_func_t
+ dtrace_nfscl_attrcache_get_miss_probe;
+uint32_t nfscl_attrcache_get_miss_id;
+
+dtrace_nfsclient_attrcache_load_probe_func_t
+ dtrace_nfscl_attrcache_load_done_probe;
+uint32_t nfscl_attrcache_load_done_id;
+#endif /* !KDTRACE_HOOKS */
+
extern u_int32_t newnfs_true, newnfs_false, newnfs_xdrneg1;
extern struct vop_vector newnfs_vnodeops;
extern struct vop_vector newnfs_fifoops;
@@ -105,7 +127,7 @@ nfscl_nget(struct mount *mntp, struct vnode *dvp, struct nfsfh *nfhp,
if (error == 0 && nvp != NULL) {
/*
* I believe there is a slight chance that vgonel() could
- * get called on this vnode between when vn_lock() drops
+ * get called on this vnode between when NFSVOPLOCK() drops
* the VI_LOCK() and vget() acquires it again, so that it
* hasn't yet had v_usecount incremented. If this were to
* happen, the VI_DOOMED flag would be set, so check for
@@ -295,7 +317,7 @@ nfscl_ngetreopen(struct mount *mntp, u_int8_t *fhp, int fhsize,
error = vfs_hash_get(mntp, hash, (LK_EXCLUSIVE | LK_NOWAIT), td, &nvp,
newnfs_vncmpf, nfhp);
if (error == 0 && nvp != NULL) {
- VOP_UNLOCK(nvp, 0);
+ NFSVOPUNLOCK(nvp, 0);
} else if (error == EBUSY) {
/*
* The LK_EXCLOTHER lock type tells nfs_lock1() to not try
@@ -366,6 +388,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
np->n_vattr.na_mtime = nap->na_mtime;
np->n_vattr.na_ctime = nap->na_ctime;
np->n_vattr.na_fsid = nap->na_fsid;
+ np->n_vattr.na_mode = nap->na_mode;
} else {
NFSBCOPY((caddr_t)nap, (caddr_t)&np->n_vattr,
sizeof (struct nfsvattr));
@@ -407,6 +430,7 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
*/
vap->va_size = np->n_size;
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
} else if (np->n_flag & NMODIFIED) {
/*
* We've modified the file: Use the larger
@@ -439,9 +463,11 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
* We detect this by for the mtime moving back. We invalidate the
* attrcache when this happens.
*/
- if (timespeccmp(&mtime_save, &vap->va_mtime, >))
+ if (timespeccmp(&mtime_save, &vap->va_mtime, >)) {
/* Size changed or mtime went backwards */
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ }
if (vaper != NULL) {
NFSBCOPY((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
if (np->n_flag & NCHG) {
@@ -451,6 +477,10 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
vaper->va_mtime = np->n_mtim;
}
}
+#ifdef KDTRACE_HOOKS
+ if (np->n_attrstamp != 0)
+ KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, 0);
+#endif
NFSUNLOCKNODE(np);
return (0);
}
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 5d83d0b..b88f7b8 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -585,7 +585,7 @@ APPLESTATIC void
nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p)
{
struct nfsrv_descript nfsd, *nd = &nfsd;
- struct nfscllockowner *lp;
+ struct nfscllockowner *lp, *nlp;
struct nfscllock *lop, *nlop;
struct ucred *tcred;
u_int64_t off = 0, len = 0;
@@ -642,6 +642,14 @@ nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p)
}
nfscl_freelock(lop, 0);
}
+ /*
+ * Do a ReleaseLockOwner.
+ * The lock owner name nfsl_owner may be used by other opens for
+ * other files but the lock_owner4 name that nfsrpc_rellockown()
+ * puts on the wire has the file handle for this file appended
+ * to it, so it can be done now.
+ */
+ (void)nfsrpc_rellockown(nmp, lp, tcred, p);
}
/*
@@ -659,20 +667,8 @@ nfsrpc_doclose(struct nfsmount *nmp, struct nfsclopen *op, NFSPROC_T *p)
NFSLOCKCLSTATE();
nfscl_lockunlock(&op->nfso_own->nfsow_rwlock);
- /*
- * Move the lockowner to nfsc_defunctlockowner,
- * so the Renew thread will do the ReleaseLockOwner
- * Op on it later. There might still be other
- * opens using the same lockowner name.
- */
- lp = LIST_FIRST(&op->nfso_lock);
- if (lp != NULL) {
- while (LIST_NEXT(lp, nfsl_list) != NULL)
- lp = LIST_NEXT(lp, nfsl_list);
- LIST_PREPEND(&nmp->nm_clp->nfsc_defunctlockowner,
- &op->nfso_lock, lp, nfsl_list);
- LIST_INIT(&op->nfso_lock);
- }
+ LIST_FOREACH_SAFE(lp, &op->nfso_lock, nfsl_list, nlp)
+ nfscl_freelockowner(lp, 0);
nfscl_freeopen(op, 0);
NFSUNLOCKCLSTATE();
NFSFREECRED(tcred);
@@ -1527,8 +1523,8 @@ nfsrpc_writerpc(vnode_t vp, struct uio *uiop, int *iomode,
* deadlock, is that the upcall times out and allows
* the write to complete. However, progress is so slow
* that it might just as well be deadlocked.
- * So, we just get the attributes that change with each
- * write Op.
+ * As such, we get the rest of the attributes, but not
+ * Owner or Owner_group.
* nb: nfscl_loadattrcache() needs to be told that these
* partial attributes from a write rpc are being
* passed in, via a argument flag.
@@ -3629,7 +3625,8 @@ nfsrpc_lockt(struct nfsrv_descript *nd, vnode_t vp,
{
u_int32_t *tl;
int error, type, size;
- u_int8_t own[NFSV4CL_LOCKNAMELEN];
+ uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
+ struct nfsnode *np;
NFSCL_REQSTART(nd, NFSPROC_LOCKT, vp);
NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
@@ -3644,7 +3641,10 @@ nfsrpc_lockt(struct nfsrv_descript *nd, vnode_t vp,
*tl++ = clp->nfsc_clientid.lval[0];
*tl = clp->nfsc_clientid.lval[1];
nfscl_filllockowner(id, own, flags);
- (void) nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN);
+ np = VTONFS(vp);
+ NFSBCOPY(np->n_fhp->nfh_fh, &own[NFSV4CL_LOCKNAMELEN],
+ np->n_fhp->nfh_len);
+ (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + np->n_fhp->nfh_len);
error = nfscl_request(nd, vp, p, cred, NULL);
if (error)
return (error);
@@ -3744,6 +3744,7 @@ nfsrpc_lock(struct nfsrv_descript *nd, struct nfsmount *nmp, vnode_t vp,
{
u_int32_t *tl;
int error, size;
+ uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL);
NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
@@ -3768,7 +3769,9 @@ nfsrpc_lock(struct nfsrv_descript *nd, struct nfsmount *nmp, vnode_t vp,
*tl++ = txdr_unsigned(lp->nfsl_seqid);
*tl++ = lp->nfsl_open->nfso_own->nfsow_clp->nfsc_clientid.lval[0];
*tl = lp->nfsl_open->nfso_own->nfsow_clp->nfsc_clientid.lval[1];
- (void) nfsm_strtom(nd, lp->nfsl_owner, NFSV4CL_LOCKNAMELEN);
+ NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
+ NFSBCOPY(nfhp, &own[NFSV4CL_LOCKNAMELEN], fhlen);
+ (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN + fhlen);
} else {
*tl = newnfs_false;
NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + NFSX_UNSIGNED);
@@ -4029,12 +4032,17 @@ nfsrpc_rellockown(struct nfsmount *nmp, struct nfscllockowner *lp,
struct nfsrv_descript nfsd, *nd = &nfsd;
u_int32_t *tl;
int error;
+ uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
*tl++ = nmp->nm_clp->nfsc_clientid.lval[0];
*tl = nmp->nm_clp->nfsc_clientid.lval[1];
- (void) nfsm_strtom(nd, lp->nfsl_owner, NFSV4CL_LOCKNAMELEN);
+ NFSBCOPY(lp->nfsl_owner, own, NFSV4CL_LOCKNAMELEN);
+ NFSBCOPY(lp->nfsl_open->nfso_fh, &own[NFSV4CL_LOCKNAMELEN],
+ lp->nfsl_open->nfso_fhlen);
+ (void)nfsm_strtom(nd, own, NFSV4CL_LOCKNAMELEN +
+ lp->nfsl_open->nfso_fhlen);
nd->nd_flag |= ND_USEGSSNAME;
error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
NFS_PROG, NFS_VER4, NULL, 1, NULL);
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index aa81437..7ce2b8e 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -95,7 +95,7 @@ int nfscl_deleghighwater = NFSCLDELEGHIGHWATER;
static int nfscl_delegcnt = 0;
static int nfscl_getopen(struct nfsclownerhead *, u_int8_t *, int, u_int8_t *,
- NFSPROC_T *, u_int32_t, struct nfsclowner **, struct nfsclopen **);
+ u_int8_t *, u_int32_t, struct nfscllockowner **, struct nfsclopen **);
static void nfscl_clrelease(struct nfsclclient *);
static void nfscl_cleanclient(struct nfsclclient *);
static void nfscl_expireclient(struct nfsclclient *, struct nfsmount *,
@@ -114,7 +114,6 @@ static struct nfscldeleg *nfscl_finddeleg(struct nfsclclient *, u_int8_t *,
int);
static int nfscl_checkconflict(struct nfscllockownerhead *, struct nfscllock *,
u_int8_t *, struct nfscllock **);
-static void nfscl_freelockowner(struct nfscllockowner *, int);
static void nfscl_freealllocks(struct nfscllockownerhead *, int);
static int nfscl_localconflict(struct nfsclclient *, u_int8_t *, int,
struct nfscllock *, u_int8_t *, struct nfscldeleg *, struct nfscllock **);
@@ -522,25 +521,20 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
* for a matching OpenOwner and use that.
*/
nfscl_filllockowner(p->td_proc, own, F_POSIX);
- error = nfscl_getopen(&clp->nfsc_owner, nfhp, fhlen, NULL, p,
- mode, NULL, &op);
- if (error == 0) {
- /* now look for a lockowner */
- LIST_FOREACH(lp, &op->nfso_lock, nfsl_list) {
- if (!NFSBCMP(lp->nfsl_owner, own,
- NFSV4CL_LOCKNAMELEN)) {
- stateidp->seqid =
- lp->nfsl_stateid.seqid;
- stateidp->other[0] =
- lp->nfsl_stateid.other[0];
- stateidp->other[1] =
- lp->nfsl_stateid.other[1];
- stateidp->other[2] =
- lp->nfsl_stateid.other[2];
- NFSUNLOCKCLSTATE();
- return (0);
- }
- }
+ lp = NULL;
+ error = nfscl_getopen(&clp->nfsc_owner, nfhp, fhlen, own, own,
+ mode, &lp, &op);
+ if (error == 0 && lp != NULL) {
+ stateidp->seqid =
+ lp->nfsl_stateid.seqid;
+ stateidp->other[0] =
+ lp->nfsl_stateid.other[0];
+ stateidp->other[1] =
+ lp->nfsl_stateid.other[1];
+ stateidp->other[2] =
+ lp->nfsl_stateid.other[2];
+ NFSUNLOCKCLSTATE();
+ return (0);
}
}
if (op == NULL) {
@@ -579,55 +573,74 @@ nfscl_getstateid(vnode_t vp, u_int8_t *nfhp, int fhlen, u_int32_t mode,
}
/*
- * Get an existing open. Search up the parentage tree for a match and
- * return with the first one found.
+ * Search for a matching file, mode and, optionally, lockowner.
*/
static int
nfscl_getopen(struct nfsclownerhead *ohp, u_int8_t *nfhp, int fhlen,
- u_int8_t *rown, NFSPROC_T *p, u_int32_t mode, struct nfsclowner **owpp,
- struct nfsclopen **opp)
+ u_int8_t *openown, u_int8_t *lockown, u_int32_t mode,
+ struct nfscllockowner **lpp, struct nfsclopen **opp)
{
- struct nfsclowner *owp = NULL;
- struct nfsclopen *op;
- NFSPROC_T *nproc;
- u_int8_t own[NFSV4CL_LOCKNAMELEN], *ownp;
+ struct nfsclowner *owp;
+ struct nfsclopen *op, *rop, *rop2;
+ struct nfscllockowner *lp;
+ int keep_looping;
- nproc = p;
- op = NULL;
- while (op == NULL && (nproc != NULL || rown != NULL)) {
- if (nproc != NULL) {
- nfscl_filllockowner(nproc->td_proc, own, F_POSIX);
- ownp = own;
- } else {
- ownp = rown;
- }
- /* Search the client list */
- LIST_FOREACH(owp, ohp, nfsow_list) {
- if (!NFSBCMP(owp->nfsow_owner, ownp,
- NFSV4CL_LOCKNAMELEN))
- break;
- }
- if (owp != NULL) {
- /* and look for the correct open */
- LIST_FOREACH(op, &owp->nfsow_open, nfso_list) {
- if (op->nfso_fhlen == fhlen &&
- !NFSBCMP(op->nfso_fh, nfhp, fhlen)
- && (op->nfso_mode & mode) == mode) {
- break;
+ if (lpp != NULL)
+ *lpp = NULL;
+ /*
+ * rop will be set to the open to be returned. There are three
+ * variants of this, all for an open of the correct file:
+ * 1 - A match of lockown.
+ * 2 - A match of the openown, when no lockown match exists.
+ * 3 - A match for any open, if no openown or lockown match exists.
+ * Looking for #2 over #3 probably isn't necessary, but since
+ * RFC3530 is vague w.r.t. the relationship between openowners and
+ * lockowners, I think this is the safer way to go.
+ */
+ rop = NULL;
+ rop2 = NULL;
+ keep_looping = 1;
+ /* Search the client list */
+ owp = LIST_FIRST(ohp);
+ while (owp != NULL && keep_looping != 0) {
+ /* and look for the correct open */
+ op = LIST_FIRST(&owp->nfsow_open);
+ while (op != NULL && keep_looping != 0) {
+ if (op->nfso_fhlen == fhlen &&
+ !NFSBCMP(op->nfso_fh, nfhp, fhlen)
+ && (op->nfso_mode & mode) == mode) {
+ if (lpp != NULL) {
+ /* Now look for a matching lockowner. */
+ LIST_FOREACH(lp, &op->nfso_lock,
+ nfsl_list) {
+ if (!NFSBCMP(lp->nfsl_owner,
+ lockown,
+ NFSV4CL_LOCKNAMELEN)) {
+ *lpp = lp;
+ rop = op;
+ keep_looping = 0;
+ break;
+ }
+ }
+ }
+ if (rop == NULL && !NFSBCMP(owp->nfsow_owner,
+ openown, NFSV4CL_LOCKNAMELEN)) {
+ rop = op;
+ if (lpp == NULL)
+ keep_looping = 0;
}
+ if (rop2 == NULL)
+ rop2 = op;
}
+ op = LIST_NEXT(op, nfso_list);
}
- if (rown != NULL)
- break;
- if (op == NULL)
- nproc = nfscl_getparent(nproc);
+ owp = LIST_NEXT(owp, nfsow_list);
}
- if (op == NULL) {
+ if (rop == NULL)
+ rop = rop2;
+ if (rop == NULL)
return (EBADF);
- }
- if (owpp)
- *owpp = owp;
- *opp = op;
+ *opp = rop;
return (0);
}
@@ -748,7 +761,8 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
FREE((caddr_t)newclp, M_NFSCLCLIENT);
}
NFSLOCKCLSTATE();
- while ((clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID) == 0 && !igotlock)
+ while ((clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID) == 0 && !igotlock &&
+ (mp->mnt_kern_flag & MNTK_UNMOUNTF) == 0)
igotlock = nfsv4_lock(&clp->nfsc_lock, 1, NULL,
NFSCLSTATEMUTEXPTR, mp);
if (!igotlock)
@@ -892,16 +906,16 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
struct nfscldeleg *dp = NULL, *ldp = NULL;
struct nfscllockownerhead *lhp = NULL;
struct nfsnode *np;
- u_int8_t own[NFSV4CL_LOCKNAMELEN], *ownp;
+ u_int8_t own[NFSV4CL_LOCKNAMELEN], *ownp, openown[NFSV4CL_LOCKNAMELEN];
+ u_int8_t *openownp;
int error = 0, ret, donelocally = 0;
u_int32_t mode;
- if (type == F_WRLCK)
- mode = NFSV4OPEN_ACCESSWRITE;
- else
- mode = NFSV4OPEN_ACCESSREAD;
+ /* For Lock Ops, the open mode doesn't matter, so use 0 to match any. */
+ mode = 0;
np = VTONFS(vp);
*lpp = NULL;
+ lp = NULL;
*newonep = 0;
*donelocallyp = 0;
@@ -941,9 +955,12 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
op = NULL;
if (recovery) {
ownp = rownp;
+ openownp = ropenownp;
} else {
nfscl_filllockowner(id, own, flags);
ownp = own;
+ nfscl_filllockowner(p->td_proc, openown, F_POSIX);
+ openownp = openown;
}
if (!recovery) {
NFSLOCKCLSTATE();
@@ -962,13 +979,13 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
dp = NULL;
}
if (dp != NULL) {
- /* Now, find the associated open to get the correct openowner */
+ /* Now, find an open and maybe a lockowner. */
ret = nfscl_getopen(&dp->nfsdl_owner, np->n_fhp->nfh_fh,
- np->n_fhp->nfh_len, NULL, p, mode, NULL, &op);
+ np->n_fhp->nfh_len, openownp, ownp, mode, NULL, &op);
if (ret)
ret = nfscl_getopen(&clp->nfsc_owner,
- np->n_fhp->nfh_fh, np->n_fhp->nfh_len, NULL, p,
- mode, NULL, &op);
+ np->n_fhp->nfh_fh, np->n_fhp->nfh_len, openownp,
+ ownp, mode, NULL, &op);
if (!ret) {
lhp = &dp->nfsdl_lock;
TAILQ_REMOVE(&clp->nfsc_deleg, dp, nfsdl_list);
@@ -981,16 +998,11 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
}
if (!donelocally) {
/*
- * Get the related Open.
+ * Get the related Open and maybe lockowner.
*/
- if (recovery)
- error = nfscl_getopen(&clp->nfsc_owner,
- np->n_fhp->nfh_fh, np->n_fhp->nfh_len, ropenownp,
- NULL, mode, NULL, &op);
- else
- error = nfscl_getopen(&clp->nfsc_owner,
- np->n_fhp->nfh_fh, np->n_fhp->nfh_len, NULL, p,
- mode, NULL, &op);
+ error = nfscl_getopen(&clp->nfsc_owner,
+ np->n_fhp->nfh_fh, np->n_fhp->nfh_len, openownp,
+ ownp, mode, &lp, &op);
if (!error)
lhp = &op->nfso_lock;
}
@@ -1011,10 +1023,11 @@ nfscl_getbytelock(vnode_t vp, u_int64_t off, u_int64_t len,
/*
* Ok, see if a lockowner exists and create one, as required.
*/
- LIST_FOREACH(lp, lhp, nfsl_list) {
- if (!NFSBCMP(lp->nfsl_owner, ownp, NFSV4CL_LOCKNAMELEN))
- break;
- }
+ if (lp == NULL)
+ LIST_FOREACH(lp, lhp, nfsl_list) {
+ if (!NFSBCMP(lp->nfsl_owner, ownp, NFSV4CL_LOCKNAMELEN))
+ break;
+ }
if (lp == NULL) {
NFSBCOPY(ownp, nlp->nfsl_owner, NFSV4CL_LOCKNAMELEN);
if (recovery)
@@ -1450,7 +1463,7 @@ nfscl_freeopenowner(struct nfsclowner *owp, int local)
/*
* Free up a byte range lock owner structure.
*/
-static void
+APPLESTATIC void
nfscl_freelockowner(struct nfscllockowner *lp, int local)
{
struct nfscllock *lop, *nlop;
diff --git a/sys/fs/nfsclient/nfs_clsubs.c b/sys/fs/nfsclient/nfs_clsubs.c
index 0c05631..f64cf2d 100644
--- a/sys/fs/nfsclient/nfs_clsubs.c
+++ b/sys/fs/nfsclient/nfs_clsubs.c
@@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+
/*
* These functions support the macros and help fiddle mbuf chains for
* the nfs op functions. They do things like create the rpc header and
@@ -68,6 +70,7 @@ __FBSDID("$FreeBSD$");
#include <fs/nfsclient/nfsnode.h>
#include <fs/nfsclient/nfsmount.h>
#include <fs/nfsclient/nfs.h>
+#include <fs/nfsclient/nfs_kdtrace.h>
#include <netinet/in.h>
@@ -140,12 +143,12 @@ ncl_upgrade_vnlock(struct vnode *vp)
int old_lock;
ASSERT_VOP_LOCKED(vp, "ncl_upgrade_vnlock");
- old_lock = VOP_ISLOCKED(vp);
+ old_lock = NFSVOPISLOCKED(vp);
if (old_lock != LK_EXCLUSIVE) {
KASSERT(old_lock == LK_SHARED,
("ncl_upgrade_vnlock: wrong old_lock %d", old_lock));
/* Upgrade to exclusive lock, this might block */
- vn_lock(vp, LK_UPGRADE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
}
return (old_lock);
}
@@ -156,7 +159,7 @@ ncl_downgrade_vnlock(struct vnode *vp, int old_lock)
if (old_lock != LK_EXCLUSIVE) {
KASSERT(old_lock == LK_SHARED, ("wrong old_lock %d", old_lock));
/* Downgrade from exclusive lock. */
- vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_DOWNGRADE | LK_RETRY);
}
}
@@ -238,6 +241,7 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper)
#ifdef NFS_ACDEBUG
mtx_unlock(&Giant); /* ncl_printf() */
#endif
+ KDTRACE_NFS_ATTRCACHE_GET_MISS(vp);
return( ENOENT);
}
newnfsstats.attrcache_hits++;
@@ -267,6 +271,7 @@ ncl_getattrcache(struct vnode *vp, struct vattr *vaper)
#ifdef NFS_ACDEBUG
mtx_unlock(&Giant); /* ncl_printf() */
#endif
+ KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
return (0);
}
diff --git a/sys/fs/nfsclient/nfs_clvfsops.c b/sys/fs/nfsclient/nfs_clvfsops.c
index d962a54..3339428 100644
--- a/sys/fs/nfsclient/nfs_clvfsops.c
+++ b/sys/fs/nfsclient/nfs_clvfsops.c
@@ -1344,7 +1344,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
/*
* Lose the lock but keep the ref.
*/
- VOP_UNLOCK(*vpp, 0);
+ NFSVOPUNLOCK(*vpp, 0);
return (0);
}
error = EIO;
@@ -1477,7 +1477,7 @@ loop:
VI_LOCK(vp);
MNT_IUNLOCK(mp);
/* XXX Racy bv_cnt check. */
- if (VOP_ISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
+ if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 ||
waitfor == MNT_LAZY) {
VI_UNLOCK(vp);
MNT_ILOCK(mp);
@@ -1491,7 +1491,7 @@ loop:
error = VOP_FSYNC(vp, waitfor, td);
if (error)
allerror = error;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
vrele(vp);
MNT_ILOCK(mp);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 3e1c66d..a69c76e 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
* vnode op calls for Sun NFS version 2, 3 and 4
*/
+#include "opt_kdtrace.h"
#include "opt_inet.h"
#include <sys/param.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <fs/nfsclient/nfsnode.h>
#include <fs/nfsclient/nfsmount.h>
#include <fs/nfsclient/nfs.h>
+#include <fs/nfsclient/nfs_kdtrace.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -77,6 +79,24 @@ __FBSDID("$FreeBSD$");
#include <nfs/nfs_lock.h>
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+dtrace_nfsclient_accesscache_flush_probe_func_t
+ dtrace_nfscl_accesscache_flush_done_probe;
+uint32_t nfscl_accesscache_flush_done_id;
+
+dtrace_nfsclient_accesscache_get_probe_func_t
+ dtrace_nfscl_accesscache_get_hit_probe,
+ dtrace_nfscl_accesscache_get_miss_probe;
+uint32_t nfscl_accesscache_get_hit_id;
+uint32_t nfscl_accesscache_get_miss_id;
+
+dtrace_nfsclient_accesscache_load_probe_func_t
+ dtrace_nfscl_accesscache_load_done_probe;
+uint32_t nfscl_accesscache_load_done_id;
+#endif /* !KDTRACE_HOOKS */
+
/* Defs */
#define TRUE 1
#define FALSE 0
@@ -298,9 +318,15 @@ nfs34_access_otw(struct vnode *vp, int wmode, struct thread *td,
mtx_unlock(&np->n_mtx);
if (retmode != NULL)
*retmode = rmode;
+ KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0);
} else if (NFS_ISV4(vp)) {
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
}
+#ifdef KDTRACE_HOOKS
+ if (error != 0)
+ KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0,
+ error);
+#endif
return (error);
}
@@ -397,6 +423,14 @@ nfs_access(struct vop_access_args *ap)
}
}
mtx_unlock(&np->n_mtx);
+#ifdef KDTRACE_HOOKS
+ if (gotahit != 0)
+ KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp,
+ ap->a_cred->cr_uid, mode);
+ else
+ KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp,
+ ap->a_cred->cr_uid, mode);
+#endif
if (gotahit == 0) {
/*
* Either a no, or a don't know. Go to the wire.
@@ -507,6 +541,7 @@ nfs_open(struct vop_open_args *ap)
}
mtx_lock(&np->n_mtx);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
if (vp->v_type == VDIR)
np->n_direofoffset = 0;
mtx_unlock(&np->n_mtx);
@@ -692,8 +727,10 @@ nfs_close(struct vop_close_args *ap)
* is the cause of some caching/coherency issue that might
* crop up.)
*/
- if (VFSTONFS(vp->v_mount)->nm_negnametimeo == 0)
+ if (VFSTONFS(vp->v_mount)->nm_negnametimeo == 0) {
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ }
if (np->n_flag & NWRITEERR) {
np->n_flag &= ~NWRITEERR;
error = np->n_error;
@@ -949,6 +986,7 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
np->n_accesscache[i].stamp = 0;
np->n_flag |= NDELEGMOD;
mtx_unlock(&np->n_mtx);
+ KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
}
error = nfsrpc_setattr(vp, vap, NULL, cred, td, &nfsva, &attrflag,
NULL);
@@ -1030,6 +1068,7 @@ nfs_lookup(struct vop_lookup_args *ap)
!(newnp->n_flag & NMODIFIED)) {
mtx_lock(&newnp->n_mtx);
newnp->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
mtx_unlock(&newnp->n_mtx);
}
if (nfscl_nodeleg(newvp, 0) == 0 ||
@@ -1170,13 +1209,13 @@ nfs_lookup(struct vop_lookup_args *ap)
}
if (flags & ISDOTDOT) {
- ltype = VOP_ISLOCKED(dvp);
+ ltype = NFSVOPISLOCKED(dvp);
error = vfs_busy(mp, MBF_NOWAIT);
if (error != 0) {
vfs_ref(mp);
- VOP_UNLOCK(dvp, 0);
+ NFSVOPUNLOCK(dvp, 0);
error = vfs_busy(mp, 0);
- vn_lock(dvp, ltype | LK_RETRY);
+ NFSVOPLOCK(dvp, ltype | LK_RETRY);
vfs_rel(mp);
if (error == 0 && (dvp->v_iflag & VI_DOOMED)) {
vfs_unbusy(mp);
@@ -1185,14 +1224,14 @@ nfs_lookup(struct vop_lookup_args *ap)
if (error != 0)
return (error);
}
- VOP_UNLOCK(dvp, 0);
+ NFSVOPUNLOCK(dvp, 0);
error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL,
cnp->cn_lkflags);
if (error == 0)
newvp = NFSTOV(np);
vfs_unbusy(mp);
if (newvp != dvp)
- vn_lock(dvp, ltype | LK_RETRY);
+ NFSVOPLOCK(dvp, ltype | LK_RETRY);
if (dvp->v_iflag & VI_DOOMED) {
if (error == 0) {
if (newvp == dvp)
@@ -1233,6 +1272,7 @@ nfs_lookup(struct vop_lookup_args *ap)
*/
mtx_lock(&np->n_mtx);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
mtx_unlock(&np->n_mtx);
}
}
@@ -1412,8 +1452,10 @@ nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
dnp = VTONFS(dvp);
mtx_lock(&dnp->n_mtx);
dnp->n_flag |= NMODIFIED;
- if (!dattrflag)
+ if (!dattrflag) {
dnp->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&dnp->n_mtx);
return (error);
}
@@ -1566,8 +1608,10 @@ again:
}
mtx_lock(&dnp->n_mtx);
dnp->n_flag |= NMODIFIED;
- if (!dattrflag)
+ if (!dattrflag) {
dnp->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&dnp->n_mtx);
return (error);
}
@@ -1630,6 +1674,7 @@ nfs_remove(struct vop_remove_args *ap)
mtx_lock(&np->n_mtx);
np->n_attrstamp = 0;
mtx_unlock(&np->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
return (error);
}
@@ -1678,8 +1723,10 @@ nfs_removerpc(struct vnode *dvp, struct vnode *vp, char *name,
(void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
mtx_lock(&dnp->n_mtx);
dnp->n_flag |= NMODIFIED;
- if (!dattrflag)
+ if (!dattrflag) {
dnp->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&dnp->n_mtx);
if (error && NFS_ISV4(dvp))
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
@@ -1717,7 +1764,7 @@ nfs_rename(struct vop_rename_args *ap)
error = 0;
goto out;
}
- if ((error = vn_lock(fvp, LK_EXCLUSIVE)) != 0)
+ if ((error = NFSVOPLOCK(fvp, LK_EXCLUSIVE)) != 0)
goto out;
/*
@@ -1734,7 +1781,7 @@ nfs_rename(struct vop_rename_args *ap)
* this condition can result in potential (silent) data loss.
*/
error = VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_thread);
- VOP_UNLOCK(fvp, 0);
+ NFSVOPUNLOCK(fvp, 0);
if (!error && tvp)
error = VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_thread);
if (error)
@@ -1857,6 +1904,7 @@ nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp, char *fnameptr,
} else {
fdnp->n_attrstamp = 0;
mtx_unlock(&fdnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp);
}
mtx_lock(&tdnp->n_mtx);
tdnp->n_flag |= NMODIFIED;
@@ -1866,6 +1914,7 @@ nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp, char *fnameptr,
} else {
tdnp->n_attrstamp = 0;
mtx_unlock(&tdnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
}
if (error && NFS_ISV4(fdvp))
error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
@@ -1908,6 +1957,7 @@ nfs_link(struct vop_link_args *ap)
} else {
tdnp->n_attrstamp = 0;
mtx_unlock(&tdnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
}
if (attrflag)
(void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
@@ -1916,6 +1966,7 @@ nfs_link(struct vop_link_args *ap)
mtx_lock(&np->n_mtx);
np->n_attrstamp = 0;
mtx_unlock(&np->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
}
/*
* If negative lookup caching is enabled, I might as well
@@ -2002,6 +2053,7 @@ nfs_symlink(struct vop_symlink_args *ap)
} else {
dnp->n_attrstamp = 0;
mtx_unlock(&dnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
}
return (error);
}
@@ -2037,6 +2089,7 @@ nfs_mkdir(struct vop_mkdir_args *ap)
} else {
dnp->n_attrstamp = 0;
mtx_unlock(&dnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
}
if (nfhp) {
ret = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, cnp->cn_thread,
@@ -2105,6 +2158,7 @@ nfs_rmdir(struct vop_rmdir_args *ap)
} else {
dnp->n_attrstamp = 0;
mtx_unlock(&dnp->n_mtx);
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
}
cache_purge(dvp);
@@ -2889,9 +2943,9 @@ nfs_advlock(struct vop_advlock_args *ap)
cred = p->p_ucred;
else
cred = td->td_ucred;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (EBADF);
}
@@ -2914,27 +2968,27 @@ nfs_advlock(struct vop_advlock_args *ap)
ap->a_fl, 0, cred, td, ap->a_id, ap->a_flags);
if (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) &&
ap->a_op == F_SETLK) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
error = nfs_catnap(PZERO | PCATCH, ret,
"ncladvl");
if (error)
return (EINTR);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_iflag & VI_DOOMED) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (EBADF);
}
}
} while (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) &&
ap->a_op == F_SETLK);
if (ret == NFSERR_DENIED) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (EAGAIN);
} else if (ret == EINVAL || ret == EBADF || ret == EINTR) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (ret);
} else if (ret != 0) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (EACCES);
}
@@ -2946,12 +3000,14 @@ nfs_advlock(struct vop_advlock_args *ap)
if (ap->a_op == F_SETLK) {
if ((np->n_flag & NMODIFIED) == 0) {
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
ret = VOP_GETATTR(vp, &va, cred);
}
if ((np->n_flag & NMODIFIED) || ret ||
np->n_change != va.va_filerev) {
(void) ncl_vinvalbuf(vp, V_SAVE, td, 1);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
ret = VOP_GETATTR(vp, &va, cred);
if (!ret) {
np->n_mtime = va.va_mtime;
@@ -2959,21 +3015,21 @@ nfs_advlock(struct vop_advlock_args *ap)
}
}
}
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
return (0);
} else if (!NFS_ISV4(vp)) {
- error = vn_lock(vp, LK_SHARED);
+ error = NFSVOPLOCK(vp, LK_SHARED);
if (error)
return (error);
if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
size = VTONFS(vp)->n_size;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
error = lf_advlock(ap, &(vp->v_lockf), size);
} else {
if (nfs_advlock_p != NULL)
error = nfs_advlock_p(ap);
else {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
error = ENOLCK;
}
}
@@ -2993,15 +3049,15 @@ nfs_advlockasync(struct vop_advlockasync_args *ap)
if (NFS_ISV4(vp))
return (EOPNOTSUPP);
- error = vn_lock(vp, LK_SHARED);
+ error = NFSVOPLOCK(vp, LK_SHARED);
if (error)
return (error);
if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
size = VTONFS(vp)->n_size;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
error = lf_advlockasync(ap, &(vp->v_lockf), size);
} else {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
error = EOPNOTSUPP;
}
return (error);
diff --git a/sys/fs/nfsclient/nfs_kdtrace.h b/sys/fs/nfsclient/nfs_kdtrace.h
new file mode 100644
index 0000000..f8f143f
--- /dev/null
+++ b/sys/fs/nfsclient/nfs_kdtrace.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NFSCL_NFS_KDTRACE_H_
+#define _NFSCL_NFS_KDTRACE_H_
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+/*
+ * Definitions for NFS access cache probes.
+ */
+extern uint32_t nfscl_accesscache_flush_done_id;
+extern uint32_t nfscl_accesscache_get_hit_id;
+extern uint32_t nfscl_accesscache_get_miss_id;
+extern uint32_t nfscl_accesscache_load_done_id;
+
+#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp) do { \
+ if (dtrace_nfscl_accesscache_flush_done_probe != NULL) \
+ (dtrace_nfscl_accesscache_flush_done_probe)( \
+ nfscl_accesscache_flush_done_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode) do { \
+ if (dtrace_nfscl_accesscache_get_hit_probe != NULL) \
+ (dtrace_nfscl_accesscache_get_hit_probe)( \
+ nfscl_accesscache_get_hit_id, (vp), (uid), \
+ (mode)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode) do { \
+ if (dtrace_nfscl_accesscache_get_miss_probe != NULL) \
+ (dtrace_nfscl_accesscache_get_miss_probe)( \
+ nfscl_accesscache_get_miss_id, (vp), (uid), \
+ (mode)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error) do { \
+ if (dtrace_nfscl_accesscache_load_done_probe != NULL) \
+ (dtrace_nfscl_accesscache_load_done_probe)( \
+ nfscl_accesscache_load_done_id, (vp), (uid), \
+ (rmode), (error)); \
+} while (0)
+
+/*
+ * Definitions for NFS attribute cache probes.
+ */
+extern uint32_t nfscl_attrcache_flush_done_id;
+extern uint32_t nfscl_attrcache_get_hit_id;
+extern uint32_t nfscl_attrcache_get_miss_id;
+extern uint32_t nfscl_attrcache_load_done_id;
+
+#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp) do { \
+ if (dtrace_nfscl_attrcache_flush_done_probe != NULL) \
+ (dtrace_nfscl_attrcache_flush_done_probe)( \
+ nfscl_attrcache_flush_done_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap) do { \
+ if (dtrace_nfscl_attrcache_get_hit_probe != NULL) \
+ (dtrace_nfscl_attrcache_get_hit_probe)( \
+ nfscl_attrcache_get_hit_id, (vp), (vap)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp) do { \
+ if (dtrace_nfscl_attrcache_get_miss_probe != NULL) \
+ (dtrace_nfscl_attrcache_get_miss_probe)( \
+ nfscl_attrcache_get_miss_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error) do { \
+ if (dtrace_nfscl_attrcache_load_done_probe != NULL) \
+ (dtrace_nfscl_attrcache_load_done_probe)( \
+ nfscl_attrcache_load_done_id, (vp), (vap), \
+ (error)); \
+} while (0)
+
+#else /* !KDTRACE_HOOKS */
+
+#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp)
+#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode)
+#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode)
+#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error)
+
+#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp)
+#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap)
+#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp)
+#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error)
+
+#endif /* KDTRACE_HOOKS */
+
+#endif /* !_NFSCL_NFS_KDTRACE_H_ */
diff --git a/sys/fs/nfsserver/nfs_nfsdcache.c b/sys/fs/nfsserver/nfs_nfsdcache.c
index bcffd6c..50f92ad 100644
--- a/sys/fs/nfsserver/nfs_nfsdcache.c
+++ b/sys/fs/nfsserver/nfs_nfsdcache.c
@@ -308,6 +308,7 @@ nfsrvd_getcache(struct nfsrv_descript *nd, struct socket *so)
ret = nfsrc_gettcp(nd, newrp);
}
nfsrc_trimcache(nd->nd_sockref, so);
+ NFSEXITCODE2(0, nd);
return (ret);
}
@@ -373,7 +374,7 @@ loop:
}
nfsrc_unlock(rp);
free((caddr_t)newrp, M_NFSRVCACHE);
- return (ret);
+ goto out;
}
}
newnfsstats.srvcache_misses++;
@@ -394,7 +395,11 @@ loop:
TAILQ_INSERT_TAIL(&nfsrvudplru, newrp, rc_lru);
NFSUNLOCKCACHE();
nd->nd_rp = newrp;
- return (RC_DOIT);
+ ret = RC_DOIT;
+
+out:
+ NFSEXITCODE2(0, nd);
+ return (ret);
}
/*
@@ -405,6 +410,7 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so)
{
struct nfsrvcache *rp;
struct nfsrvcache *retrp = NULL;
+ mbuf_t m;
rp = nd->nd_rp;
if (!rp)
@@ -435,8 +441,7 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so)
M_COPYALL, M_WAIT);
rp->rc_timestamp = NFSD_MONOSEC + NFSRVCACHE_TCPTIMEOUT;
nfsrc_unlock(rp);
- nfsrc_trimcache(nd->nd_sockref, so);
- return (retrp);
+ goto out;
}
/*
@@ -457,9 +462,9 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so)
}
if ((nd->nd_flag & ND_NFSV2) &&
nfsv2_repstat[newnfsv2_procid[nd->nd_procnum]]) {
- NFSUNLOCKCACHE();
rp->rc_status = nd->nd_repstat;
rp->rc_flag |= RC_REPSTATUS;
+ NFSUNLOCKCACHE();
} else {
if (!(rp->rc_flag & RC_UDP)) {
nfsrc_tcpsavedreplies++;
@@ -469,9 +474,11 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so)
nfsrc_tcpsavedreplies;
}
NFSUNLOCKCACHE();
- rp->rc_reply = m_copym(nd->nd_mreq, 0, M_COPYALL,
- M_WAIT);
+ m = m_copym(nd->nd_mreq, 0, M_COPYALL, M_WAIT);
+ NFSLOCKCACHE();
+ rp->rc_reply = m;
rp->rc_flag |= RC_REPMBUF;
+ NFSUNLOCKCACHE();
}
if (rp->rc_flag & RC_UDP) {
rp->rc_timestamp = NFSD_MONOSEC +
@@ -489,7 +496,10 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so)
nfsrc_freecache(rp);
NFSUNLOCKCACHE();
}
+
+out:
nfsrc_trimcache(nd->nd_sockref, so);
+ NFSEXITCODE2(0, nd);
return (retrp);
}
@@ -518,6 +528,7 @@ nfsrvd_delcache(struct nfsrvcache *rp)
APPLESTATIC void
nfsrvd_sentcache(struct nfsrvcache *rp, struct socket *so, int err)
{
+ tcp_seq tmp_seq;
if (!(rp->rc_flag & RC_LOCKED))
panic("nfsrvd_sentcache not locked");
@@ -526,8 +537,12 @@ nfsrvd_sentcache(struct nfsrvcache *rp, struct socket *so, int err)
so->so_proto->pr_domain->dom_family != AF_INET6) ||
so->so_proto->pr_protocol != IPPROTO_TCP)
panic("nfs sent cache");
- if (nfsrv_getsockseqnum(so, &rp->rc_tcpseq))
+ if (nfsrv_getsockseqnum(so, &tmp_seq)) {
+ NFSLOCKCACHE();
+ rp->rc_tcpseq = tmp_seq;
rp->rc_flag |= RC_TCPSEQ;
+ NFSUNLOCKCACHE();
+ }
}
nfsrc_unlock(rp);
}
@@ -648,7 +663,7 @@ tryagain:
}
nfsrc_unlock(rp);
free((caddr_t)newrp, M_NFSRVCACHE);
- return (ret);
+ goto out;
}
newnfsstats.srvcache_misses++;
newnfsstats.srvcache_size++;
@@ -662,7 +677,11 @@ tryagain:
LIST_INSERT_HEAD(hp, newrp, rc_hash);
NFSUNLOCKCACHE();
nd->nd_rp = newrp;
- return (RC_DOIT);
+ ret = RC_DOIT;
+
+out:
+ NFSEXITCODE2(0, nd);
+ return (ret);
}
/*
@@ -687,8 +706,11 @@ nfsrc_lock(struct nfsrvcache *rp)
static void
nfsrc_unlock(struct nfsrvcache *rp)
{
+
+ NFSLOCKCACHE();
rp->rc_flag &= ~RC_LOCKED;
nfsrc_wanted(rp);
+ NFSUNLOCKCACHE();
}
/*
diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c
index 8ce70fa..ae676f3 100644
--- a/sys/fs/nfsserver/nfs_nfsdkrpc.c
+++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c
@@ -115,7 +115,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
if (rqst->rq_proc > NFSV2PROC_STATFS) {
svcerr_noproc(rqst);
svc_freereq(rqst);
- return;
+ goto out;
}
nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc];
nd.nd_flag = ND_NFSV2;
@@ -123,7 +123,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
if (rqst->rq_proc >= NFS_V3NPROCS) {
svcerr_noproc(rqst);
svc_freereq(rqst);
- return;
+ goto out;
}
nd.nd_procnum = rqst->rq_proc;
nd.nd_flag = ND_NFSV3;
@@ -132,7 +132,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
rqst->rq_proc != NFSV4PROC_COMPOUND) {
svcerr_noproc(rqst);
svc_freereq(rqst);
- return;
+ goto out;
}
nd.nd_procnum = rqst->rq_proc;
nd.nd_flag = ND_NFSV4;
@@ -192,7 +192,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
svcerr_weakauth(rqst);
svc_freereq(rqst);
m_freem(nd.nd_mrep);
- return;
+ goto out;
}
}
@@ -201,7 +201,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
svcerr_weakauth(rqst);
svc_freereq(rqst);
m_freem(nd.nd_mrep);
- return;
+ goto out;
}
/* Set the flag based on credflavor */
@@ -215,7 +215,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
svcerr_weakauth(rqst);
svc_freereq(rqst);
m_freem(nd.nd_mrep);
- return;
+ goto out;
}
#ifdef MAC
@@ -227,7 +227,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
svcerr_weakauth(rqst);
svc_freereq(rqst);
m_freem(nd.nd_mrep);
- return;
+ goto out;
}
}
@@ -248,13 +248,13 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
if (nd.nd_mreq != NULL)
m_freem(nd.nd_mreq);
svc_freereq(rqst);
- return;
+ goto out;
}
if (nd.nd_mreq == NULL) {
svcerr_decode(rqst);
svc_freereq(rqst);
- return;
+ goto out;
}
if (nd.nd_repstat & NFSERR_AUTHERR) {
@@ -267,6 +267,9 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
if (rp != NULL)
nfsrvd_sentcache(rp, xprt->xp_socket, 0);
svc_freereq(rqst);
+
+out:
+ NFSEXITCODE(0);
}
/*
@@ -329,6 +332,8 @@ nfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so,
cacherep = RC_REPLY;
*rpp = nfsrvd_updatecache(nd, so);
}
+
+ NFSEXITCODE2(0, nd);
return (cacherep);
}
@@ -340,7 +345,7 @@ nfsrvd_addsock(struct file *fp)
{
int siz;
struct socket *so;
- int error;
+ int error = 0;
SVCXPRT *xprt;
static u_int64_t sockref = 0;
@@ -348,9 +353,8 @@ nfsrvd_addsock(struct file *fp)
siz = sb_max_adj;
error = soreserve(so, siz, siz);
- if (error) {
- return (error);
- }
+ if (error)
+ goto out;
/*
* Steal the socket from userland so that it doesn't close
@@ -376,7 +380,9 @@ nfsrvd_addsock(struct file *fp)
SVC_RELEASE(xprt);
}
- return (0);
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -386,18 +392,14 @@ nfsrvd_addsock(struct file *fp)
int
nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args)
{
-#ifdef KGSSAPI
char principal[MAXHOSTNAMELEN + 5];
- int error;
+ int error = 0;
bool_t ret2, ret3, ret4;
-#endif
-#ifdef KGSSAPI
error = copyinstr(args->principal, principal, sizeof (principal),
NULL);
if (error)
- return (error);
-#endif
+ goto out;
/*
* Only the first nfsd actually does any work. The RPC code
@@ -412,38 +414,29 @@ nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args)
NFSD_UNLOCK();
-#ifdef KGSSAPI
/* An empty string implies AUTH_SYS only. */
if (principal[0] != '\0') {
- ret2 = rpc_gss_set_svc_name(principal, "kerberosv5",
- GSS_C_INDEFINITE, NFS_PROG, NFS_VER2);
- ret3 = rpc_gss_set_svc_name(principal, "kerberosv5",
- GSS_C_INDEFINITE, NFS_PROG, NFS_VER3);
- ret4 = rpc_gss_set_svc_name(principal, "kerberosv5",
- GSS_C_INDEFINITE, NFS_PROG, NFS_VER4);
-
- if (!ret2 || !ret3 || !ret4) {
- NFSD_LOCK();
- newnfs_numnfsd--;
- nfsrvd_init(1);
- NFSD_UNLOCK();
- return (EAUTH);
- }
+ ret2 = rpc_gss_set_svc_name_call(principal,
+ "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER2);
+ ret3 = rpc_gss_set_svc_name_call(principal,
+ "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER3);
+ ret4 = rpc_gss_set_svc_name_call(principal,
+ "kerberosv5", GSS_C_INDEFINITE, NFS_PROG, NFS_VER4);
+
+ if (!ret2 || !ret3 || !ret4)
+ printf("nfsd: can't register svc name\n");
}
-#endif
nfsrvd_pool->sp_minthreads = args->minthreads;
nfsrvd_pool->sp_maxthreads = args->maxthreads;
svc_run(nfsrvd_pool);
-#ifdef KGSSAPI
if (principal[0] != '\0') {
- rpc_gss_clear_svc_name(NFS_PROG, NFS_VER2);
- rpc_gss_clear_svc_name(NFS_PROG, NFS_VER3);
- rpc_gss_clear_svc_name(NFS_PROG, NFS_VER4);
+ rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER2);
+ rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER3);
+ rpc_gss_clear_svc_name_call(NFS_PROG, NFS_VER4);
}
-#endif
NFSD_LOCK();
newnfs_numnfsd--;
@@ -451,7 +444,9 @@ nfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args)
}
NFSD_UNLOCK();
- return (0);
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 5b96729..56c563a 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -116,14 +116,16 @@ nfsvno_getattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred,
* locked by this thread or not locked by this thread.
* As such, shared lock it, if not exclusively locked.
*/
- if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
+ if (NFSVOPISLOCKED(vp) != LK_EXCLUSIVE) {
lockedit = 1;
- vn_lock(vp, LK_SHARED | LK_RETRY);
+ NFSVOPLOCK(vp, LK_SHARED | LK_RETRY);
}
}
error = VOP_GETATTR(vp, &nvap->na_vattr, cred);
if (lockedit != 0)
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
+
+ NFSEXITCODE(error);
return (error);
}
@@ -138,6 +140,8 @@ nfsvno_getfh(struct vnode *vp, fhandle_t *fhp, struct thread *p)
NFSBZERO((caddr_t)fhp, sizeof(fhandle_t));
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
error = VOP_VPTOFH(vp, &fhp->fh_fid);
+
+ NFSEXITCODE(error);
return (error);
}
@@ -160,8 +164,10 @@ nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred,
int error = 0, getret = 0;
if (vpislocked == 0) {
- if (vn_lock(vp, LK_SHARED) != 0)
- return (EPERM);
+ if (NFSVOPLOCK(vp, LK_SHARED) != 0) {
+ error = EPERM;
+ goto out;
+ }
}
if (accmode & VWRITE) {
/* Just vn_writechk() changed to check rdonly */
@@ -191,8 +197,8 @@ nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred,
}
if (error != 0) {
if (vpislocked == 0)
- VOP_UNLOCK(vp, 0);
- return (error);
+ NFSVOPUNLOCK(vp, 0);
+ goto out;
}
/*
@@ -231,7 +237,10 @@ nfsvno_accchk(struct vnode *vp, accmode_t accmode, struct ucred *cred,
}
}
if (vpislocked == 0)
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -245,6 +254,7 @@ nfsvno_setattr(struct vnode *vp, struct nfsvattr *nvap, struct ucred *cred,
int error;
error = VOP_SETATTR(vp, &nvap->na_vattr, cred);
+ NFSEXITCODE(error);
return (error);
}
@@ -279,10 +289,11 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
else
vrele(dp);
nfsvno_relpathbuf(ndp);
- return (ENOTDIR);
+ error = ENOTDIR;
+ goto out1;
}
if (islocked)
- NFSVOPUNLOCK(dp, 0, p);
+ NFSVOPUNLOCK(dp, 0);
VREF(dp);
*retdirp = dp;
if (NFSVNO_EXRDONLY(exp))
@@ -351,7 +362,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0)
nfsvno_relpathbuf(ndp);
if (ndp->ni_vp && !lockleaf)
- NFSVOPUNLOCK(ndp->ni_vp, 0, p);
+ NFSVOPUNLOCK(ndp->ni_vp, 0);
break;
}
@@ -359,7 +370,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
* Validate symlink
*/
if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
- NFSVOPUNLOCK(ndp->ni_dvp, 0, p);
+ NFSVOPUNLOCK(ndp->ni_dvp, 0);
if (!(nd->nd_flag & ND_PUBLOOKUP)) {
error = EINVAL;
goto badlink2;
@@ -444,6 +455,9 @@ out:
} else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
ndp->ni_dvp = NULL;
}
+
+out1:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -487,7 +501,7 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p,
struct iovec *ivp = iv;
struct uio io, *uiop = &io;
struct mbuf *mp, *mp2 = NULL, *mp3 = NULL;
- int i, len, tlen, error;
+ int i, len, tlen, error = 0;
len = 0;
i = 0;
@@ -523,7 +537,7 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p,
if (error) {
m_freem(mp3);
*lenp = 0;
- return (error);
+ goto out;
}
if (uiop->uio_resid > 0) {
len -= uiop->uio_resid;
@@ -533,7 +547,10 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p,
*lenp = len;
*mpp = mp3;
*mpendp = mp;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -650,7 +667,7 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred,
if (error) {
m_freem(m3);
*mpp = NULL;
- return (error);
+ goto out;
}
tlen = len - uiop->uio_resid;
cnt = cnt < tlen ? cnt : tlen;
@@ -662,7 +679,10 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred,
nfsrv_adj(m3, len - tlen, tlen - cnt);
*mpp = m3;
*mpendp = m2;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -712,6 +732,8 @@ nfsvno_write(struct vnode *vp, off_t off, int retlen, int cnt, int stable,
uiop->uio_offset = off;
error = VOP_WRITE(vp, uiop, ioflags, cred);
FREE((caddr_t)iv, M_TEMP);
+
+ NFSEXITCODE(error);
return (error);
}
@@ -758,7 +780,7 @@ nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp,
vrele(ndp->ni_startdir);
nfsvno_relpathbuf(ndp);
vput(ndp->ni_dvp);
- return (error);
+ goto out;
}
nvap->na_rdev = rdev;
error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp,
@@ -767,12 +789,13 @@ nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp,
nfsvno_relpathbuf(ndp);
vrele(ndp->ni_startdir);
if (error)
- return (error);
+ goto out;
} else {
vrele(ndp->ni_startdir);
nfsvno_relpathbuf(ndp);
vput(ndp->ni_dvp);
- return (ENXIO);
+ error = ENXIO;
+ goto out;
}
*vpp = ndp->ni_vp;
} else {
@@ -804,6 +827,9 @@ nfsvno_createsub(struct nfsrv_descript *nd, struct nameidata *ndp,
if (error)
vput(*vpp);
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -826,13 +852,15 @@ nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred,
nfsvno_relpathbuf(ndp);
vput(ndp->ni_dvp);
vrele(ndp->ni_vp);
- return (EEXIST);
+ error = EEXIST;
+ goto out;
}
if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
vrele(ndp->ni_startdir);
nfsvno_relpathbuf(ndp);
vput(ndp->ni_dvp);
- return (NFSERR_BADTYPE);
+ error = NFSERR_BADTYPE;
+ goto out;
}
if (vtyp == VSOCK) {
vrele(ndp->ni_startdir);
@@ -846,7 +874,7 @@ nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred,
vrele(ndp->ni_startdir);
nfsvno_relpathbuf(ndp);
vput(ndp->ni_dvp);
- return (error);
+ goto out;
}
error = VOP_MKNOD(ndp->ni_dvp, &ndp->ni_vp,
&ndp->ni_cnd, &nvap->na_vattr);
@@ -858,6 +886,9 @@ nfsvno_mknod(struct nameidata *ndp, struct nfsvattr *nvap, struct ucred *cred,
* see any reason to do the lookup.
*/
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -877,12 +908,16 @@ nfsvno_mkdir(struct nameidata *ndp, struct nfsvattr *nvap, uid_t saved_uid,
vput(ndp->ni_dvp);
vrele(ndp->ni_vp);
nfsvno_relpathbuf(ndp);
- return (EEXIST);
+ error = EEXIST;
+ goto out;
}
error = VOP_MKDIR(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd,
&nvap->na_vattr);
vput(ndp->ni_dvp);
nfsvno_relpathbuf(ndp);
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -904,7 +939,8 @@ nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp,
else
vput(ndp->ni_dvp);
vrele(ndp->ni_vp);
- return (EEXIST);
+ error = EEXIST;
+ goto out;
}
error = VOP_SYMLINK(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd,
@@ -920,6 +956,9 @@ nfsvno_symlink(struct nameidata *ndp, struct nfsvattr *nvap, char *pathcp,
*/
if (!not_v2 && !error)
vput(ndp->ni_vp);
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -960,10 +999,12 @@ nfsvno_getsymlink(struct nfsrv_descript *nd, struct nfsvattr *nvap,
}
*pathcpp = pathcp;
*lenp = len;
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
if (pathcp)
free(pathcp, M_TEMP);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -989,6 +1030,7 @@ nfsvno_removesub(struct nameidata *ndp, int is_v4, struct ucred *cred,
else
vput(ndp->ni_dvp);
vput(vp);
+ NFSEXITCODE(error);
return (error);
}
@@ -1027,6 +1069,7 @@ out:
else
vput(ndp->ni_dvp);
vput(vp);
+ NFSEXITCODE(error);
return (error);
}
@@ -1097,9 +1140,9 @@ nfsvno_rename(struct nameidata *fromndp, struct nameidata *tondp,
goto out;
}
if (ndflag & ND_NFSV4) {
- if (vn_lock(fvp, LK_EXCLUSIVE) == 0) {
+ if (NFSVOPLOCK(fvp, LK_EXCLUSIVE) == 0) {
error = nfsrv_checkremove(fvp, 0, p);
- VOP_UNLOCK(fvp, 0);
+ NFSVOPUNLOCK(fvp, 0);
} else
error = EPERM;
if (tvp && !error)
@@ -1136,6 +1179,7 @@ out:
out1:
vrele(fromndp->ni_startdir);
nfsvno_relpathbuf(fromndp);
+ NFSEXITCODE(error);
return (error);
}
@@ -1158,7 +1202,7 @@ nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
error = EXDEV;
}
if (!error) {
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) == 0)
error = VOP_LINK(ndp->ni_dvp, vp, &ndp->ni_cnd);
else
@@ -1167,7 +1211,7 @@ nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
vrele(ndp->ni_dvp);
else
vput(ndp->ni_dvp);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
} else {
if (ndp->ni_dvp == ndp->ni_vp)
vrele(ndp->ni_dvp);
@@ -1177,6 +1221,7 @@ nfsvno_link(struct nameidata *ndp, struct vnode *vp, struct ucred *cred,
vrele(ndp->ni_vp);
}
nfsvno_relpathbuf(ndp);
+ NFSEXITCODE(error);
return (error);
}
@@ -1271,6 +1316,7 @@ nfsvno_fsync(struct vnode *vp, u_int64_t off, int cnt, struct ucred *cred,
}
BO_UNLOCK(bo);
}
+ NFSEXITCODE(error);
return (error);
}
@@ -1296,6 +1342,7 @@ nfsvno_statfs(struct vnode *vp, struct statfs *sf)
if (sf->f_ffree < 0)
sf->f_ffree = 0;
}
+ NFSEXITCODE(error);
return (error);
}
@@ -1386,6 +1433,8 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
}
}
*vpp = vp;
+
+ NFSEXITCODE2(0, nd);
}
/*
@@ -1419,6 +1468,7 @@ nfsvno_fillattr(struct nfsrv_descript *nd, struct mount *mp, struct vnode *vp,
error = nfsv4_fillattr(nd, mp, vp, NULL, &nvap->na_vattr, fhp, rderror,
attrbitp, cred, p, isdgram, reterr, supports_nfsv4acls, at_root,
mounted_on_fileno);
+ NFSEXITCODE2(0, nd);
return (error);
}
@@ -1465,7 +1515,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
@@ -1512,7 +1562,7 @@ nfsrvd_readdir(struct nfsrv_descript *nd, int isdgram,
vput(vp);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
@@ -1556,7 +1606,7 @@ again:
free((caddr_t)cookies, M_TEMP);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
/*
* If nothing read, return eof
@@ -1576,7 +1626,7 @@ again:
*tl = newnfs_true;
FREE((caddr_t)rbuf, M_TEMP);
FREE((caddr_t)cookies, M_TEMP);
- return (0);
+ goto out;
}
/*
@@ -1677,9 +1727,13 @@ again:
*tl = newnfs_false;
FREE((caddr_t)rbuf, M_TEMP);
FREE((caddr_t)cookies, M_TEMP);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1714,7 +1768,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
off = fxdr_hyper(tl);
@@ -1786,7 +1840,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdgram,
vput(vp);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs");
@@ -1826,7 +1880,7 @@ again:
free((caddr_t)rbuf, M_TEMP);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
/*
* If nothing read, return eof
@@ -1843,7 +1897,7 @@ again:
*tl = newnfs_true;
free((caddr_t)cookies, M_TEMP);
free((caddr_t)rbuf, M_TEMP);
- return (0);
+ goto out;
}
/*
@@ -1887,7 +1941,7 @@ again:
*/
mp = vp->v_mount;
vfs_ref(mp);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
nd->nd_repstat = vfs_busy(mp, 0);
vfs_rel(mp);
if (nd->nd_repstat != 0) {
@@ -1896,7 +1950,7 @@ again:
free(rbuf, M_TEMP);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
/*
@@ -1986,7 +2040,7 @@ again:
dp->d_name[1] == '.')
cn.cn_flags |=
ISDOTDOT;
- if (vn_lock(vp, LK_SHARED)
+ if (NFSVOPLOCK(vp, LK_SHARED)
!= 0) {
nd->nd_repstat = EPERM;
break;
@@ -2001,7 +2055,7 @@ again:
r = VOP_LOOKUP(vp, &nvp,
&cn);
if (vp != nvp)
- VOP_UNLOCK(vp,
+ NFSVOPUNLOCK(vp,
0);
}
}
@@ -2080,7 +2134,7 @@ again:
if (nvp != NULL) {
supports_nfsv4acls =
nfs_supportsnfsv4acls(nvp);
- VOP_UNLOCK(nvp, 0);
+ NFSVOPUNLOCK(nvp, 0);
} else
supports_nfsv4acls = 0;
if (refp != NULL) {
@@ -2148,9 +2202,13 @@ again:
}
FREE((caddr_t)cookies, M_TEMP);
FREE((caddr_t)rbuf, M_TEMP);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2249,6 +2307,7 @@ nfsrv_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
error = nfsv4_sattr(nd, nvap, attrbitp, aclp, p);
};
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2272,7 +2331,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
error = nfsrv_getattrbits(nd, attrbitp, NULL, &retnotsup);
if (error)
- return (error);
+ goto nfsmout;
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
attrsize = fxdr_unsigned(int, *tl);
@@ -2304,7 +2363,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
if (error)
goto nfsmout;
if (aceerr && !nd->nd_repstat)
- nd->nd_repstat = NFSERR_ATTRNOTSUPP;
+ nd->nd_repstat = aceerr;
attrsum += aclsize;
break;
case NFSATTRBIT_ARCHIVE:
@@ -2337,8 +2396,10 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
case NFSATTRBIT_OWNER:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
j = fxdr_unsigned(int, *tl);
- if (j < 0)
- return (NFSERR_BADXDR);
+ if (j < 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
if (j > NFSV4_SMALLSTR)
cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
else
@@ -2347,7 +2408,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
if (error) {
if (j > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
- return (error);
+ goto nfsmout;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsv4_strtouid(cp,j,&uid,p);
@@ -2361,8 +2422,10 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
case NFSATTRBIT_OWNERGROUP:
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
j = fxdr_unsigned(int, *tl);
- if (j < 0)
- return (NFSERR_BADXDR);
+ if (j < 0) {
+ error = NFSERR_BADXDR;
+ goto nfsmout;
+ }
if (j > NFSV4_SMALLSTR)
cp = malloc(j + 1, M_NFSSTRING, M_WAITOK);
else
@@ -2371,7 +2434,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
if (error) {
if (j > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
- return (error);
+ goto nfsmout;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsv4_strtogid(cp,j,&gid,p);
@@ -2453,6 +2516,7 @@ nfsv4_sattr(struct nfsrv_descript *nd, struct nfsvattr *nvap,
error = nfsm_advance(nd, attrsize - attrsum, -1);
}
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2484,14 +2548,16 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp,
error = NFSERR_WRONGSEC;
else
error = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- return (error);
+ goto out;
}
/*
* Check to see if the file system is exported V4 only.
*/
- if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4))
- return (NFSERR_PROGNOTV4);
+ if (NFSVNO_EXV4ONLY(exp) && !(nd->nd_flag & ND_NFSV4)) {
+ error = NFSERR_PROGNOTV4;
+ goto out;
+ }
/*
* Now, map the user credentials.
@@ -2508,7 +2574,10 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff *exp,
crsetgroups(nd->nd_cred, credanon->cr_ngroups,
credanon->cr_groups);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -2533,6 +2602,7 @@ nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
for (i = 0; i < exp->nes_numsecflavor; i++)
exp->nes_secflavors[i] = secflavors[i];
}
+ NFSEXITCODE(error);
return (error);
}
@@ -2578,50 +2648,9 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
* but this will have to do until VFS_FHTOVP() has a lock
* type argument like VFS_VGET().
*/
- vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY);
- return (error);
-}
-
-/*
- * Do the pathconf vnode op.
- */
-int
-nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf,
- struct ucred *cred, struct thread *p)
-{
- int error;
+ NFSVOPLOCK(*vpp, LK_DOWNGRADE | LK_RETRY);
- error = VOP_PATHCONF(vp, flag, retf);
- if (error == EOPNOTSUPP || error == EINVAL) {
- /*
- * Some file systems return EINVAL for name arguments not
- * supported and some return EOPNOTSUPP for this case.
- * So the NFSv3 Pathconf RPC doesn't fail for these cases,
- * just fake them.
- */
- switch (flag) {
- case _PC_LINK_MAX:
- *retf = LINK_MAX;
- break;
- case _PC_NAME_MAX:
- *retf = NAME_MAX;
- break;
- case _PC_CHOWN_RESTRICTED:
- *retf = 1;
- break;
- case _PC_NO_TRUNC:
- *retf = 1;
- break;
- default:
- /*
- * Only happens if a _PC_xxx is added to the server,
- * but this isn't updated.
- */
- *retf = 0;
- printf("nfsrvd pathconf flag=%d not supp\n", flag);
- };
- error = 0;
- }
+ NFSEXITCODE(error);
return (error);
}
@@ -2653,7 +2682,7 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
if (mp == NULL) {
*vpp = NULL;
nd->nd_repstat = ESTALE;
- return;
+ goto out;
}
if (startwrite)
@@ -2723,6 +2752,9 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp, int lktype,
if (mpp != NULL)
*mpp = NULL;
}
+
+out:
+ NFSEXITCODE2(0, nd);
}
/*
@@ -2733,13 +2765,19 @@ fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp)
{
struct filedesc *fdp;
struct file *fp;
+ int error = 0;
fdp = p->td_proc->p_fd;
if (fd >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[fd]) == NULL)
- return (EBADF);
+ (fp = fdp->fd_ofiles[fd]) == NULL) {
+ error = EBADF;
+ goto out;
+ }
*fpp = fp;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -2751,7 +2789,7 @@ int
nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)
{
struct nfsex_args *nfsexargp = (struct nfsex_args *)argp;
- int error;
+ int error = 0;
struct nameidata nd;
fhandle_t fh;
@@ -2759,15 +2797,17 @@ nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)
if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0)
nfs_rootfhset = 0;
else if (error == 0) {
- if (nfsexargp->fspec == NULL)
- return (EPERM);
+ if (nfsexargp->fspec == NULL) {
+ error = EPERM;
+ goto out;
+ }
/*
* If fspec != NULL, this is the v4root path.
*/
NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_USERSPACE,
nfsexargp->fspec, p);
if ((error = namei(&nd)) != 0)
- return (error);
+ goto out;
error = nfsvno_getfh(nd.ni_vp, &fh, p);
vrele(nd.ni_vp);
if (!error) {
@@ -2778,6 +2818,9 @@ nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)
nfs_rootfhset = 1;
}
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -2790,23 +2833,29 @@ nfsrv_getsocksndseq(struct socket *so, tcp_seq *maxp, tcp_seq *unap)
{
struct inpcb *inp;
struct tcpcb *tp;
+ int error = 0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("nfsrv_getsocksndseq: inp == NULL"));
INP_RLOCK(inp);
if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
INP_RUNLOCK(inp);
- return (EPIPE);
+ error = EPIPE;
+ goto out;
}
tp = intotcpcb(inp);
if (tp->t_state != TCPS_ESTABLISHED) {
INP_RUNLOCK(inp);
- return (EPIPE);
+ error = EPIPE;
+ goto out;
}
*maxp = tp->snd_max;
*unap = tp->snd_una;
INP_RUNLOCK(inp);
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -2878,16 +2927,18 @@ int
nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
u_int64_t end, struct thread *td)
{
- int error;
+ int error = 0;
struct flock fl;
u_int64_t tlen;
if (nfsrv_dolocallocks == 0)
- return (0);
+ goto out;
/* Check for VI_DOOMED here, so that VOP_ADVLOCK() isn't performed. */
- if ((vp->v_iflag & VI_DOOMED) != 0)
- return (EPERM);
+ if ((vp->v_iflag & VI_DOOMED) != 0) {
+ error = EPERM;
+ goto out;
+ }
fl.l_whence = SEEK_SET;
fl.l_type = ftype;
@@ -2911,14 +2962,17 @@ nfsvno_advlock(struct vnode *vp, int ftype, u_int64_t first,
fl.l_pid = (pid_t)0;
fl.l_sysid = (int)nfsv4_sysid;
- NFSVOPUNLOCK(vp, 0, td);
+ NFSVOPUNLOCK(vp, 0);
if (ftype == F_UNLCK)
error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_UNLCK, &fl,
(F_POSIX | F_REMOTE));
else
error = VOP_ADVLOCK(vp, (caddr_t)td->td_proc, F_SETLK, &fl,
(F_POSIX | F_REMOTE));
- NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY, td);
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -2929,12 +2983,14 @@ int
nfsvno_v4rootexport(struct nfsrv_descript *nd)
{
struct ucred *credanon;
- int exflags, error, numsecflavor, *secflavors, i;
+ int exflags, error = 0, numsecflavor, *secflavors, i;
error = vfs_stdcheckexp(&nfsv4root_mnt, nd->nd_nam, &exflags,
&credanon, &numsecflavor, &secflavors);
- if (error)
- return (NFSERR_PROGUNAVAIL);
+ if (error) {
+ error = NFSERR_PROGUNAVAIL;
+ goto out;
+ }
if (credanon != NULL)
crfree(credanon);
for (i = 0; i < numsecflavor; i++) {
@@ -2947,7 +3003,10 @@ nfsvno_v4rootexport(struct nfsrv_descript *nd)
else if (secflavors[i] == RPCSEC_GSS_KRB5P)
nd->nd_flag |= ND_EXGSSPRIVACY;
}
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -2967,27 +3026,32 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
if (uap->flag & NFSSVC_NFSDADDSOCK) {
error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg));
if (error)
- return (error);
- if ((error = fget(td, sockarg.sock, &fp)) != 0) {
- return (error);
- }
+ goto out;
+ if ((error = fget(td, sockarg.sock, &fp)) != 0)
+ goto out;
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
- return (EPERM);
+ error = EPERM;
+ goto out;
}
error = nfsrvd_addsock(fp);
fdrop(fp, td);
} else if (uap->flag & NFSSVC_NFSDNFSD) {
- if (uap->argp == NULL)
- return (EINVAL);
+ if (uap->argp == NULL) {
+ error = EINVAL;
+ goto out;
+ }
error = copyin(uap->argp, (caddr_t)&nfsdarg,
sizeof (nfsdarg));
if (error)
- return (error);
+ goto out;
error = nfsrvd_nfsd(td, &nfsdarg);
} else {
error = nfssvc_srvcall(td, uap, td->td_ucred);
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -3085,6 +3149,8 @@ nfssvc_srvcall(struct thread *p, struct nfssvc_args *uap, struct ucred *cred)
nfsd_master_proc = procp;
PROC_UNLOCK(procp);
}
+
+ NFSEXITCODE(error);
return (error);
}
@@ -3179,7 +3245,7 @@ nfsd_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
if (loaded)
- return (0);
+ goto out;
newnfs_portinit();
mtx_init(&nfs_cache_mutex, "nfs_cache_mutex", NULL, MTX_DEF);
mtx_init(&nfs_v4root_mutex, "nfs_v4root_mutex", NULL, MTX_DEF);
@@ -3235,7 +3301,10 @@ nfsd_modevent(module_t mod, int type, void *data)
error = EOPNOTSUPP;
break;
}
- return error;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
static moduledata_t nfsd_mod = {
"nfsd",
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index ee55031..b6a365d 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -93,7 +93,7 @@ nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, 1, &nva);
- return (0);
+ goto out;
}
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nfsmode = fxdr_unsigned(u_int32_t, *tl);
@@ -103,7 +103,7 @@ nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
NFSACCESS_EXECUTE))) {
nd->nd_repstat = NFSERR_INVAL;
vput(vp);
- return (0);
+ goto out;
}
if (nfsmode & NFSACCESS_READ) {
supported |= NFSACCESS_READ;
@@ -155,9 +155,13 @@ nfsrvd_access(struct nfsrv_descript *nd, __unused int isdgram,
} else
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(nfsmode);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -172,19 +176,20 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
fhandle_t fh;
int at_root = 0, error = 0, supports_nfsv4acls;
struct nfsreferral *refp;
- nfsattrbit_t attrbits;
+ nfsattrbit_t attrbits, tmpbits;
struct mount *mp;
struct vnode *tvp = NULL;
struct vattr va;
uint64_t mounted_on_fileno = 0;
+ accmode_t accmode;
if (nd->nd_repstat)
- return (0);
+ goto out;
if (nd->nd_flag & ND_NFSV4) {
error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
if (error) {
vput(vp);
- return (error);
+ goto out;
}
/*
@@ -195,13 +200,22 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
(void) nfsrv_putreferralattr(nd, &attrbits, refp, 1,
&nd->nd_repstat);
vput(vp);
- return (0);
+ goto out;
+ }
+ if (nd->nd_repstat == 0) {
+ accmode = 0;
+ NFSSET_ATTRBIT(&tmpbits, &attrbits);
+ if (NFSISSET_ATTRBIT(&tmpbits, NFSATTRBIT_ACL)) {
+ NFSCLRBIT_ATTRBIT(&tmpbits, NFSATTRBIT_ACL);
+ accmode |= VREAD_ACL;
+ }
+ if (NFSNONZERO_ATTRBIT(&tmpbits))
+ accmode |= VREAD_ATTRIBUTES;
+ if (accmode != 0)
+ nd->nd_repstat = nfsvno_accchk(vp, accmode,
+ nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
+ NFSACCCHK_VPISLOCKED, NULL);
}
- if (!nd->nd_repstat)
- nd->nd_repstat = nfsvno_accchk(vp,
- VREAD_ATTRIBUTES,
- nd->nd_cred, exp, p, NFSACCCHK_NOOVERRIDE,
- NFSACCCHK_VPISLOCKED, NULL);
}
if (!nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
@@ -225,10 +239,10 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
} else
at_root = 0;
vfs_ref(mp);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
if (at_root != 0) {
if ((nd->nd_repstat =
- vn_lock(tvp, LK_SHARED)) == 0) {
+ NFSVOPLOCK(tvp, LK_SHARED)) == 0) {
nd->nd_repstat = VOP_GETATTR(
tvp, &va, nd->nd_cred);
vput(tvp);
@@ -260,7 +274,10 @@ nfsrvd_getattr(struct nfsrv_descript *nd, int isdgram,
} else {
vput(vp);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -280,7 +297,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
- return (0);
+ goto out;
}
#ifdef NFS4_ACL_EXTATTR_NAME
aclp = acl_alloc(M_WAITOK);
@@ -316,7 +333,7 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
acl_free(aclp);
#endif
nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
- return (0);
+ goto out;
}
} else if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV4))
nd->nd_repstat = nfsrv_checkuidgid(nd, &nva);
@@ -430,6 +447,9 @@ nfsrvd_setattr(struct nfsrv_descript *nd, __unused int isdgram,
(void) nfsrv_putattrbit(nd, &retbits);
else if (!nd->nd_repstat)
nfsrv_fillattr(nd, &nva);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
@@ -444,6 +464,7 @@ nfsmout:
*/
(void) nfsrv_putattrbit(nd, &retbits);
}
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -454,18 +475,18 @@ nfsmout:
APPLESTATIC int
nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
vnode_t dp, vnode_t *vpp, fhandle_t *fhp, NFSPROC_T *p,
- __unused struct nfsexstuff *exp)
+ struct nfsexstuff *exp)
{
struct nameidata named;
vnode_t vp, dirp = NULL;
- int error, dattr_ret = 1;
+ int error = 0, dattr_ret = 1;
struct nfsvattr nva, dattr;
char *bufp;
u_long *hashp;
if (nd->nd_repstat) {
nfsrv_postopattr(nd, dattr_ret, &dattr);
- return (0);
+ goto out;
}
/*
@@ -475,7 +496,7 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
if (dp->v_type == VLNK && (nd->nd_flag & ND_NFSV4)) {
nd->nd_repstat = NFSERR_SYMLINK;
vrele(dp);
- return (0);
+ goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
@@ -485,7 +506,7 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
if (error) {
vrele(dp);
nfsvno_relpathbuf(&named);
- return (error);
+ goto out;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
@@ -502,13 +523,21 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
}
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, dattr_ret, &dattr);
- return (0);
+ goto out;
}
if (named.ni_startdir)
vrele(named.ni_startdir);
nfsvno_relpathbuf(&named);
vp = named.ni_vp;
- nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
+ if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) &&
+ vp->v_type != VDIR && vp->v_type != VLNK)
+ /*
+ * Only allow lookup of VDIR and VLNK for traversal of
+ * non-exported volumes during NFSv4 mounting.
+ */
+ nd->nd_repstat = ENOENT;
+ if (nd->nd_repstat == 0)
+ nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
if (!(nd->nd_flag & ND_NFSV4) && !nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred, p, 1);
if (vpp != NULL && nd->nd_repstat == 0)
@@ -524,7 +553,7 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, dattr_ret, &dattr);
- return (0);
+ goto out;
}
if (nd->nd_flag & ND_NFSV2) {
(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
@@ -534,7 +563,10 @@ nfsrvd_lookup(struct nfsrv_descript *nd, __unused int isdgram,
nfsrv_postopattr(nd, 0, &nva);
nfsrv_postopattr(nd, dattr_ret, &dattr);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -551,7 +583,7 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &nva);
- return (0);
+ goto out;
}
if (vnode_vtype(vp) != VLNK) {
if (nd->nd_flag & ND_NFSV2)
@@ -568,12 +600,15 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &nva);
if (nd->nd_repstat)
- return (0);
+ goto out;
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(len);
mbuf_setnext(nd->nd_mb, mp);
nd->nd_mb = mpend;
nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
}
@@ -596,7 +631,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &nva);
- return (0);
+ goto out;
}
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
@@ -672,7 +707,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
vput(vp);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &nva);
- return (0);
+ goto out;
}
if (off >= nva.na_size) {
cnt = 0;
@@ -699,7 +734,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
mbuf_freem(m3);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &nva);
- return (0);
+ goto out;
}
}
vput(vp);
@@ -724,9 +759,13 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_mb = m2;
nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -751,7 +790,7 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
- return (0);
+ goto out;
}
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
@@ -844,7 +883,7 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
vput(vp);
if (nd->nd_flag & ND_NFSV3)
nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
- return (0);
+ goto out;
}
/*
@@ -870,7 +909,7 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
if (nd->nd_repstat)
- return (0);
+ goto out;
NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(retlen);
if (stable == NFSWRITE_UNSTABLE)
@@ -886,9 +925,13 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int isdgram,
*tl = txdr_unsigned(nfsboottime.tv_usec);
} else if (!nd->nd_repstat)
nfsrv_fillattr(nd, &nva);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -918,17 +961,14 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
LOCKPARENT | LOCKLEAF | SAVESTART);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
- if (error) {
- vput(dp);
- nfsvno_relpathbuf(&named);
- return (error);
- }
+ if (error)
+ goto nfsmout;
if (!nd->nd_repstat) {
NFSVNO_ATTRINIT(&nva);
if (nd->nd_flag & ND_NFSV2) {
@@ -983,7 +1023,7 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
&diraft);
}
vput(dp);
- return (0);
+ goto out;
}
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
@@ -1002,7 +1042,7 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
&diraft);
if (dirp)
vrele(dirp);
- return (0);
+ goto out;
}
if (!(nd->nd_flag & ND_NFSV2)) {
@@ -1056,10 +1096,14 @@ nfsrvd_create(struct nfsrv_descript *nd, __unused int isdgram,
}
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(dp);
nfsvno_relpathbuf(&named);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1088,7 +1132,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
cnflags = (LOCKPARENT | SAVESTART);
if (nd->nd_repstat) {
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
#ifdef NFS4_ACL_EXTATTR_NAME
aclp = acl_alloc(M_WAITOK);
@@ -1106,13 +1150,8 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
case NFLNK:
error = nfsvno_getsymlink(nd, &nva, p, &pathcp,
&pathlen);
- if (error) {
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- return (error);
- }
+ if (error)
+ goto nfsmout;
break;
case NFCHR:
case NFBLK:
@@ -1133,38 +1172,22 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
#ifdef NFS4_ACL_EXTATTR_NAME
acl_free(aclp);
#endif
- return (0);
- };
+ goto out;
+ }
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE, cnflags);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
- if (error) {
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- nfsvno_relpathbuf(&named);
- if (pathcp)
- FREE(pathcp, M_TEMP);
- return (error);
- }
+ if (error)
+ goto nfsmout;
if (!nd->nd_repstat) {
if (nd->nd_flag & ND_NFSV3) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
vtyp = nfsv34tov_type(*tl);
}
error = nfsrv_sattr(nd, &nva, &attrbits, aclp, p);
- if (error) {
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- nfsvno_relpathbuf(&named);
- if (pathcp)
- FREE(pathcp, M_TEMP);
- return (error);
- }
+ if (error)
+ goto nfsmout;
nva.na_type = vtyp;
if (!nd->nd_repstat && (nd->nd_flag & ND_NFSV3) &&
(vtyp == VCHR || vtyp == VBLK)) {
@@ -1193,7 +1216,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
&diraft);
- return (0);
+ goto out;
}
/*
@@ -1223,7 +1246,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
&diraft);
- return (0);
+ goto out;
}
if (dirp)
dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0);
@@ -1236,7 +1259,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
#ifdef NFS4_ACL_EXTATTR_NAME
acl_free(aclp);
#endif
- return (0);
+ goto out;
} else if (vtyp == VLNK) {
nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
&dirfor, &diraft, &diraft_ret, &attrbits,
@@ -1245,7 +1268,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
acl_free(aclp);
#endif
FREE(pathcp, M_TEMP);
- return (0);
+ goto out;
}
}
@@ -1258,7 +1281,7 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd->nd_cred,
p, 1);
if (vpp != NULL && nd->nd_repstat == 0) {
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
*vpp = vp;
} else
vput(vp);
@@ -1284,6 +1307,9 @@ nfsrvd_mknod(struct nfsrv_descript *nd, __unused int isdgram,
#ifdef NFS4_ACL_EXTATTR_NAME
acl_free(aclp);
#endif
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vrele(dp);
@@ -1294,6 +1320,8 @@ nfsmout:
nfsvno_relpathbuf(&named);
if (pathcp)
FREE(pathcp, M_TEMP);
+
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1306,7 +1334,7 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
{
struct nameidata named;
u_int32_t *tl;
- int error, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, dirfor_ret = 1, diraft_ret = 1;
vnode_t dirp = NULL;
struct nfsvattr dirfor, diraft;
char *bufp;
@@ -1314,7 +1342,7 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, DELETE,
LOCKPARENT | LOCKLEAF);
@@ -1323,7 +1351,7 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
if (error) {
vput(dp);
nfsvno_relpathbuf(&named);
- return (error);
+ goto out;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
@@ -1373,7 +1401,10 @@ nfsrvd_remove(struct nfsrv_descript *nd, __unused int isdgram,
txdr_hyper(diraft.na_filerev, tl);
}
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1385,7 +1416,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
struct nfsexstuff *toexp)
{
u_int32_t *tl;
- int error, fdirfor_ret = 1, fdiraft_ret = 1;
+ int error = 0, fdirfor_ret = 1, fdiraft_ret = 1;
int tdirfor_ret = 1, tdiraft_ret = 1;
struct nameidata fromnd, tond;
vnode_t fdirp = NULL, tdirp = NULL, tdp = NULL;
@@ -1398,7 +1429,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
nfsrv_wcc(nd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
- return (0);
+ goto out;
}
if (!(nd->nd_flag & ND_NFSV2))
fdirfor_ret = nfsvno_getattr(dp, &fdirfor, nd->nd_cred, p, 1);
@@ -1412,7 +1443,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
if (todp)
vrele(todp);
nfsvno_relpathbuf(&fromnd);
- return (error);
+ goto out;
}
if (nd->nd_flag & ND_NFSV4) {
tdp = todp;
@@ -1424,14 +1455,14 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
vput(dp);
/* todp is always NULL except NFSv4 */
nfsvno_relpathbuf(&fromnd);
- return (error);
+ goto out;
}
nd->nd_cred->cr_uid = nd->nd_saveduid;
nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 0, p);
if (tdp) {
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
p, 1);
- NFSVOPUNLOCK(tdp, 0, p);
+ NFSVOPUNLOCK(tdp, 0);
}
}
NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);
@@ -1444,7 +1475,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
vput(dp);
nfsvno_relpathbuf(&fromnd);
nfsvno_relpathbuf(&tond);
- return (error);
+ goto out;
}
}
if (nd->nd_repstat) {
@@ -1459,7 +1490,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
vput(dp);
nfsvno_relpathbuf(&fromnd);
nfsvno_relpathbuf(&tond);
- return (0);
+ goto out;
}
/*
@@ -1478,7 +1509,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
if (tdp)
vrele(tdp);
nfsvno_relpathbuf(&tond);
- return (0);
+ goto out;
}
if (vnode_vtype(fromnd.ni_vp) == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
@@ -1510,7 +1541,10 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
tl += 2;
txdr_hyper(tdiraft.na_filerev, tl);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1534,9 +1568,9 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
- NFSVOPUNLOCK(vp, 0, p);
+ NFSVOPUNLOCK(vp, 0);
if (vnode_vtype(vp) == VDIR) {
if (nd->nd_flag & ND_NFSV4)
nd->nd_repstat = NFSERR_ISDIR;
@@ -1561,12 +1595,12 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
if (error) {
vrele(vp);
/* tovp is always NULL unless NFSv4 */
- return (error);
+ goto out;
}
nfsd_fhtovp(nd, &dfh, LK_EXCLUSIVE, &dp, &tnes, NULL, 0,
p);
if (dp)
- NFSVOPUNLOCK(dp, 0, p);
+ NFSVOPUNLOCK(dp, 0);
}
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
@@ -1579,7 +1613,7 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
if (dp)
vrele(dp);
nfsvno_relpathbuf(&named);
- return (error);
+ goto out;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
@@ -1618,7 +1652,10 @@ nfsrvd_link(struct nfsrv_descript *nd, int isdgram,
tl += 2;
txdr_hyper(diraft.na_filerev, tl);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1631,14 +1668,14 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
{
struct nfsvattr nva, dirfor, diraft;
struct nameidata named;
- int error, dirfor_ret = 1, diraft_ret = 1, pathlen;
+ int error = 0, dirfor_ret = 1, diraft_ret = 1, pathlen;
vnode_t dirp = NULL;
char *bufp, *pathcp = NULL;
u_long *hashp;
if (nd->nd_repstat) {
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
if (vpp)
*vpp = NULL;
@@ -1652,7 +1689,7 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
if (error) {
vrele(dp);
nfsvno_relpathbuf(&named);
- return (error);
+ goto out;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
@@ -1690,7 +1727,10 @@ nfsrvd_symlink(struct nfsrv_descript *nd, __unused int isdgram,
}
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1717,7 +1757,7 @@ nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
nvap, nd->nd_cred, p, 1);
}
if (vpp != NULL && nd->nd_repstat == 0) {
- VOP_UNLOCK(ndp->ni_vp, 0);
+ NFSVOPUNLOCK(ndp->ni_vp, 0);
*vpp = ndp->ni_vp;
} else
vput(ndp->ni_vp);
@@ -1734,6 +1774,8 @@ nfsrvd_symlinksub(struct nfsrv_descript *nd, struct nameidata *ndp,
txdr_hyper(diraftp->na_filerev, tl);
(void) nfsrv_putattrbit(nd, attrbitp);
}
+
+ NFSEXITCODE2(0, nd);
}
/*
@@ -1747,33 +1789,27 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
struct nfsvattr nva, dirfor, diraft;
struct nameidata named;
u_int32_t *tl;
- int error, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, dirfor_ret = 1, diraft_ret = 1;
vnode_t dirp = NULL;
char *bufp;
u_long *hashp;
if (nd->nd_repstat) {
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
- return (0);
+ goto out;
}
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
LOCKPARENT | SAVENAME);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
- if (error) {
- vrele(dp);
- nfsvno_relpathbuf(&named);
- return (error);
- }
+ if (error)
+ goto nfsmout;
if (!nd->nd_repstat) {
NFSVNO_ATTRINIT(&nva);
if (nd->nd_flag & ND_NFSV3) {
error = nfsrv_sattr(nd, &nva, NULL, NULL, p);
- if (error) {
- vrele(dp);
- nfsvno_relpathbuf(&named);
- return (error);
- }
+ if (error)
+ goto nfsmout;
} else {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nva.na_mode = nfstov_mode(*tl++);
@@ -1798,7 +1834,7 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret,
&diraft);
- return (0);
+ goto out;
}
if (dirp != NULL)
dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd->nd_cred, p, 0);
@@ -1819,10 +1855,14 @@ nfsrvd_mkdir(struct nfsrv_descript *nd, __unused int isdgram,
(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 0);
nfsrv_fillattr(nd, &nva);
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vrele(dp);
nfsvno_relpathbuf(&named);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1850,7 +1890,7 @@ nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
nd->nd_repstat = nfsvno_getattr(vp, nvap, nd->nd_cred,
p, 1);
if (vpp && !nd->nd_repstat) {
- NFSVOPUNLOCK(vp, 0, p);
+ NFSVOPUNLOCK(vp, 0);
*vpp = vp;
} else {
vput(vp);
@@ -1868,6 +1908,8 @@ nfsrvd_mkdirsub(struct nfsrv_descript *nd, struct nameidata *ndp,
txdr_hyper(diraftp->na_filerev, tl);
(void) nfsrv_putattrbit(nd, attrbitp);
}
+
+ NFSEXITCODE2(0, nd);
}
/*
@@ -1884,7 +1926,7 @@ nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
- return (0);
+ goto out;
}
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
/*
@@ -1907,9 +1949,13 @@ nfsrvd_commit(struct nfsrv_descript *nd, __unused int isdgram,
*tl++ = txdr_unsigned(nfsboottime.tv_sec);
*tl = txdr_unsigned(nfsboottime.tv_usec);
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1929,7 +1975,7 @@ nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
sf = &sfs;
nd->nd_repstat = nfsvno_statfs(vp, sf);
@@ -1938,7 +1984,7 @@ nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
if (nd->nd_repstat)
- return (0);
+ goto out;
if (nd->nd_flag & ND_NFSV2) {
NFSM_BUILD(tl, u_int32_t *, NFSX_V2STATFS);
*tl++ = txdr_unsigned(NFS_V2MAXDATA);
@@ -1965,6 +2011,9 @@ nfsrvd_statfs(struct nfsrv_descript *nd, __unused int isdgram,
txdr_hyper(tval, tl); tl += 2;
*tl = 0;
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
}
@@ -1982,7 +2031,7 @@ nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
getret = nfsvno_getattr(vp, &at, nd->nd_cred, p, 1);
nfsvno_getfs(&fs, isdgram);
@@ -2001,6 +2050,9 @@ nfsrvd_fsinfo(struct nfsrv_descript *nd, int isdgram,
txdr_nfsv3time(&fs.fs_timedelta, tl);
tl += 2;
*tl = txdr_unsigned(fs.fs_properties);
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
}
@@ -2018,7 +2070,7 @@ nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
- return (0);
+ goto out;
}
nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
nd->nd_cred, p);
@@ -2049,6 +2101,9 @@ nfsrvd_pathconf(struct nfsrv_descript *nd, __unused int isdgram,
pc->pc_caseinsensitive = newnfs_false;
pc->pc_casepreserving = newnfs_true;
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
}
@@ -2218,11 +2273,13 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
(void) nfsm_strtom(nd, cf.cl_owner, cf.cl_ownerlen);
}
vput(vp);
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
if (stp)
free((caddr_t)stp, M_NFSDSTATE);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2326,11 +2383,13 @@ nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
}
}
vput(vp);
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
if (stp)
free((caddr_t)stp, M_NFSDSTATE);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2424,6 +2483,7 @@ nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
}
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2463,11 +2523,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
i = fxdr_unsigned(int, *(tl + 5));
if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
nd->nd_repstat = NFSERR_BADXDR;
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- return (0);
+ goto nfsmout;
}
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
M_NFSDSTATE, M_WAITOK);
@@ -2516,14 +2572,8 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_clientid.qval = clientid.qval;
}
error = nfsrv_mtostr(nd, stp->ls_owner, stp->ls_ownerlen);
- if (error) {
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (error);
- }
+ if (error)
+ goto nfsmout;
NFSVNO_ATTRINIT(&nva);
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
create = fxdr_unsigned(int, *tl);
@@ -2538,14 +2588,8 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
case NFSCREATE_UNCHECKED:
case NFSCREATE_GUARDED:
error = nfsv4_sattr(nd, &nva, &attrbits, aclp, p);
- if (error) {
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (error);
- }
+ if (error)
+ goto nfsmout;
/*
* If the na_gid being set is the same as that of
* the directory it is going in, clear it, since
@@ -2565,21 +2609,11 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
break;
default:
nd->nd_repstat = NFSERR_BADXDR;
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (0);
+ goto nfsmout;
};
} else if (create != NFSV4OPEN_NOCREATE) {
nd->nd_repstat = NFSERR_BADXDR;
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (0);
+ goto nfsmout;
}
/*
@@ -2605,12 +2639,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
if (nd->nd_repstat) {
nd->nd_repstat = nfsrv_opencheck(clientid,
&stateid, stp, NULL, nd, p, nd->nd_repstat);
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (0);
+ goto nfsmout;
}
if (create == NFSV4OPEN_CREATE)
NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, CREATE,
@@ -2627,6 +2656,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
#endif
FREE((caddr_t)stp, M_NFSDSTATE);
nfsvno_relpathbuf(&named);
+ NFSEXITCODE2(error, nd);
return (error);
}
if (!nd->nd_repstat) {
@@ -2676,16 +2706,11 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
break;
default:
nd->nd_repstat = NFSERR_BADXDR;
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (0);
+ goto nfsmout;
};
stp->ls_flags |= NFSLCK_RECLAIM;
vp = dp;
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) == 0)
nd->nd_repstat = nfsrv_opencheck(clientid, &stateid,
stp, vp, nd, p, nd->nd_repstat);
@@ -2693,12 +2718,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = NFSERR_PERM;
} else {
nd->nd_repstat = NFSERR_BADXDR;
- vrele(dp);
-#ifdef NFS4_ACL_EXTATTR_NAME
- acl_free(aclp);
-#endif
- FREE((caddr_t)stp, M_NFSDSTATE);
- return (0);
+ goto nfsmout;
}
/*
@@ -2747,7 +2767,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
* (ie: Leave the NFSVOPUNLOCK() about here.)
*/
if (vp)
- NFSVOPUNLOCK(vp, 0, p);
+ NFSVOPUNLOCK(vp, 0);
if (stp)
FREE((caddr_t)stp, M_NFSDSTATE);
if (!nd->nd_repstat && dirp)
@@ -2817,6 +2837,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
#ifdef NFS4_ACL_EXTATTR_NAME
acl_free(aclp);
#endif
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vrele(dp);
@@ -2825,6 +2846,7 @@ nfsmout:
#endif
if (stp)
FREE((caddr_t)stp, M_NFSDSTATE);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2866,9 +2888,11 @@ nfsrvd_close(struct nfsrv_descript *nd, __unused int isdgram,
*tl++ = txdr_unsigned(stateid.seqid);
NFSBCOPY((caddr_t)stateid.other,(caddr_t)tl,NFSX_STATEIDOTHER);
}
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2885,7 +2909,7 @@ nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
- return (0);
+ goto nfsmout;
}
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
clientid.lval[0] = *tl++;
@@ -2900,6 +2924,7 @@ nfsrvd_delegpurge(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = nfsrv_delegupdate(clientid, NULL, NULL,
NFSV4OP_DELEGPURGE, nd->nd_cred, p);
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2931,6 +2956,7 @@ nfsrvd_delegreturn(struct nfsrv_descript *nd, __unused int isdgram,
NFSV4OP_DELEGRETURN, nd->nd_cred, p);
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2947,6 +2973,7 @@ nfsrvd_getfh(struct nfsrv_descript *nd, __unused int isdgram,
vput(vp);
if (!nd->nd_repstat)
(void) nfsm_fhtom(nd, (u_int8_t *)&fh, 0, 0);
+ NFSEXITCODE2(0, nd);
return (0);
}
@@ -2990,6 +3017,7 @@ nfsrvd_openconfirm(struct nfsrv_descript *nd, __unused int isdgram,
}
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3067,6 +3095,7 @@ nfsrvd_opendowngrade(struct nfsrv_descript *nd, __unused int isdgram,
}
nfsmout:
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3083,7 +3112,7 @@ nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
- return (0);
+ goto nfsmout;
}
NFSM_DISSECT(tl, u_int32_t *, NFSX_HYPER);
clientid.lval[0] = *tl++;
@@ -3098,6 +3127,7 @@ nfsrvd_renew(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_RENEWOP|CLOPS_RENEW),
NULL, (nfsquad_t)((u_quad_t)0), nd, p);
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3115,7 +3145,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
struct nfsrvfh fh;
struct nfsexstuff retnes;
u_int32_t *sizp;
- int error, savflag, i;
+ int error = 0, savflag, i;
char *bufp;
u_long *hashp;
@@ -3129,7 +3159,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
if (error) {
vput(dp);
nfsvno_relpathbuf(&named);
- return (error);
+ goto out;
}
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
@@ -3140,7 +3170,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
if (dirp)
vrele(dirp);
if (nd->nd_repstat)
- return (0);
+ goto out;
vrele(named.ni_startdir);
nfsvno_relpathbuf(&named);
fh.nfsrvfh_len = NFSX_MYFH;
@@ -3155,7 +3185,7 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
}
nd->nd_flag = savflag;
if (nd->nd_repstat)
- return (0);
+ goto out;
/*
* Finally have the export flags for name, so we can create
@@ -3198,7 +3228,10 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
}
}
*sizp = txdr_unsigned(len);
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -3218,7 +3251,7 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
- return (0);
+ goto out;
}
NFSM_DISSECT(tl, u_int32_t *, NFSX_VERF + NFSX_UNSIGNED);
verf = (u_char *)tl;
@@ -3226,7 +3259,7 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
i = fxdr_unsigned(int, *tl);
if (i > NFSV4_OPAQUELIMIT || i <= 0) {
nd->nd_repstat = NFSERR_BADXDR;
- return (error);
+ goto nfsmout;
}
idlen = i;
if (nd->nd_flag & ND_GSS)
@@ -3302,6 +3335,9 @@ nfsrvd_setclientid(struct nfsrv_descript *nd, __unused int isdgram,
*tl++ = confirm.lval[0];
*tl = confirm.lval[1];
}
+
+out:
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
if (clp) {
@@ -3309,6 +3345,7 @@ nfsmout:
NFSFREEMUTEX(&clp->lc_req.nr_mtx);
free((caddr_t)clp, M_NFSDCLIENT);
}
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3326,7 +3363,7 @@ nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
- return (0);
+ goto nfsmout;
}
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_HYPER);
clientid.lval[0] = *tl++;
@@ -3341,6 +3378,7 @@ nfsrvd_setclientidcfrm(struct nfsrv_descript *nd,
nd->nd_repstat = nfsrv_getclient(clientid, (CLOPS_CONFIRM|CLOPS_RENEW),
NULL, confirm, nd, p);
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3377,6 +3415,7 @@ nfsrvd_verify(struct nfsrv_descript *nd, int isdgram,
}
}
vput(vp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3396,6 +3435,7 @@ nfsrvd_openattr(struct nfsrv_descript *nd, __unused int isdgram,
nd->nd_repstat = NFSERR_NOTSUPP;
nfsmout:
vrele(dp);
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3413,13 +3453,13 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
nd->nd_repstat = NFSERR_WRONGSEC;
- return (0);
+ goto nfsmout;
}
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
len = fxdr_unsigned(int, *(tl + 2));
if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
nd->nd_repstat = NFSERR_BADXDR;
- return (0);
+ goto nfsmout;
}
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + len,
M_NFSDSTATE, M_WAITOK);
@@ -3441,9 +3481,12 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
goto nfsmout;
nd->nd_repstat = nfsrv_releaselckown(stp, clientid, p);
FREE((caddr_t)stp, M_NFSDSTATE);
+
+ NFSEXITCODE2(0, nd);
return (0);
nfsmout:
if (stp)
free((caddr_t)stp, M_NFSDSTATE);
+ NFSEXITCODE2(error, nd);
return (error);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c
index 7007275..eaeb1dc 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -376,7 +376,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
if (error != EBADRPC)
printf("nfs dorpc err1=%d\n", error);
nd->nd_repstat = NFSERR_GARBAGE;
- return;
+ goto out;
}
if (nd->nd_procnum == NFSPROC_READ ||
nd->nd_procnum == NFSPROC_READDIR ||
@@ -393,7 +393,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
nfsd_fhtovp(nd, &fh, lktype, &vp, &nes,
&mp, nfs_writerpc[nd->nd_procnum], p);
if (nd->nd_repstat == NFSERR_PROGNOTV4)
- return;
+ goto out;
}
}
@@ -416,7 +416,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
NFSINCRGLOBAL(newnfsstats.srvrpccnt[nfsv3to4op[nd->nd_procnum]]);
if (mp != NULL && nfs_writerpc[nd->nd_procnum] != 0)
vn_finished_write(mp);
- return;
+ goto out;
}
/*
@@ -430,7 +430,7 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
} else {
if (nfs_retfh[nd->nd_procnum] == 1) {
if (vp)
- NFSVOPUNLOCK(vp, 0, p);
+ NFSVOPUNLOCK(vp, 0);
error = (*(nfsrv3_procs1[nd->nd_procnum]))(nd, isdgram,
vp, NULL, (fhandle_t *)fh.nfsrvfh_data, p, &nes);
} else if (nfs_retfh[nd->nd_procnum] == 2) {
@@ -469,6 +469,9 @@ nfsrvd_dorpc(struct nfsrv_descript *nd, int isdgram,
nd->nd_repstat == NFSERR_GRACE ||
nd->nd_repstat == NFSERR_NOGRACE))
nd->nd_flag &= ~ND_SAVEREPLY;
+
+out:
+ NFSEXITCODE2(0, nd);
}
/*
@@ -705,7 +708,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
vrele(vp);
vp = nvp;
cur_fsid = vp->v_mount->mnt_stat.f_fsid;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
vpnes = nes;
}
break;
@@ -720,7 +723,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
vrele(vp);
vp = nvp;
cur_fsid = vp->v_mount->mnt_stat.f_fsid;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
vpnes = nes;
}
break;
@@ -733,7 +736,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
vrele(vp);
vp = nvp;
cur_fsid = vp->v_mount->mnt_stat.f_fsid;
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
vpnes = nes;
}
} else
@@ -786,6 +789,8 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
op != NFSV4OP_LOOKUP &&
op != NFSV4OP_GETATTR &&
op != NFSV4OP_GETFH &&
+ op != NFSV4OP_ACCESS &&
+ op != NFSV4OP_READLINK &&
op != NFSV4OP_SECINFO)
nd->nd_repstat = NFSERR_NOFILEHANDLE;
else if (nfsvno_testexp(nd, &vpnes) &&
@@ -838,7 +843,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
}
}
/* Lookup ops return a locked vnode */
- VOP_UNLOCK(nvp, 0);
+ NFSVOPUNLOCK(nvp, 0);
}
if (!nd->nd_repstat) {
vrele(vp);
@@ -859,7 +864,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
}
if (nfsv4_opflag[op].modifyfs)
vn_start_write(savevp, &temp_mp, V_WAIT);
- if (vn_lock(savevp, LK_EXCLUSIVE) == 0) {
+ if (NFSVOPLOCK(savevp, LK_EXCLUSIVE) == 0) {
VREF(vp);
VREF(savevp);
error = (*(nfsrv4_ops2[op]))(nd, isdgram,
@@ -876,7 +881,7 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
if (nfsv4_opflag[op].modifyfs)
vn_start_write(vp, &temp_mp,
V_WAIT);
- if (vn_lock(vp, nfsv4_opflag[op].lktype)
+ if (NFSVOPLOCK(vp, nfsv4_opflag[op].lktype)
== 0)
VREF(vp);
else
@@ -944,4 +949,6 @@ nfsmout:
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsv4rootfs_lock);
NFSUNLOCKV4ROOTMUTEX();
+
+ NFSEXITCODE2(0, nd);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index fc84d72..bd246d5 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -135,7 +135,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
nfsquad_t *clientidp, nfsquad_t *confirmp, NFSPROC_T *p)
{
struct nfsclient *clp = NULL, *new_clp = *new_clpp;
- int i;
+ int i, error = 0;
struct nfsstate *stp, *tstp;
struct sockaddr_in *sad, *rad;
int zapit = 0, gotit, hasstate = 0, igotlock;
@@ -144,8 +144,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
/*
* Check for state resource limit exceeded.
*/
- if (nfsrv_openpluslock > NFSRV_V4STATELIMIT)
- return (NFSERR_RESOURCE);
+ if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
+ error = NFSERR_RESOURCE;
+ goto out;
+ }
if (nfsrv_issuedelegs == 0 ||
((nd->nd_flag & ND_GSS) != 0 && nfsrv_nogsscallback != 0))
@@ -228,7 +230,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
if (zapit)
nfsrv_zapclient(clp, p);
*new_clpp = NULL;
- return (0);
+ goto out;
}
/*
@@ -274,7 +276,8 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
- return (NFSERR_CLIDINUSE);
+ error = NFSERR_CLIDINUSE;
+ goto out;
}
}
@@ -335,7 +338,7 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
}
nfsrv_zapclient(clp, p);
*new_clpp = NULL;
- return (0);
+ goto out;
}
/*
* id and verifier match, so update the net address info
@@ -388,7 +391,10 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
}
nfsrv_zapclient(clp, p);
*new_clpp = NULL;
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -406,8 +412,10 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
if (clpp)
*clpp = NULL;
- if (nfsrvboottime != clientid.lval[0])
- return (NFSERR_STALECLIENTID);
+ if (nfsrvboottime != clientid.lval[0]) {
+ error = NFSERR_STALECLIENTID;
+ goto out;
+ }
/*
* If called with opflags == CLOPS_RENEW, the State Lock is
@@ -450,7 +458,7 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
} else if (opflags != CLOPS_RENEW) {
NFSUNLOCKSTATE();
}
- return (error);
+ goto out;
}
/*
@@ -526,6 +534,9 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
}
if (clpp)
*clpp = clp;
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -537,7 +548,7 @@ APPLESTATIC int
nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
{
struct nfsclient *clp = NULL;
- int i;
+ int i, error = 0;
int gotit, igotlock;
/*
@@ -570,7 +581,8 @@ nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 0);
NFSUNLOCKV4ROOTMUTEX();
- return (EPERM);
+ error = EPERM;
+ goto out;
}
/*
@@ -590,7 +602,10 @@ nfsrv_adminrevoke(struct nfsd_clid *revokep, NFSPROC_T *p)
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 0);
NFSUNLOCKV4ROOTMUTEX();
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -1229,6 +1244,7 @@ nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32
{
struct nfsstate *stp;
struct nfsstatehead *hp;
+ int error = 0;
*stpp = NULL;
hp = NFSSTATEHASH(clp, *stateidp);
@@ -1241,10 +1257,15 @@ nfsrv_getstate(struct nfsclient *clp, nfsv4stateid_t *stateidp, __unused u_int32
/*
* If no state id in list, return NFSERR_BADSTATEID.
*/
- if (stp == LIST_END(hp))
- return (NFSERR_BADSTATEID);
+ if (stp == LIST_END(hp)) {
+ error = NFSERR_BADSTATEID;
+ goto out;
+ }
*stpp = stp;
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -1323,14 +1344,16 @@ nfsrv_lockctrl(vnode_t vp, struct nfsstate **new_stpp,
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
&new_stp->ls_stateid, specialid);
if (error)
- return (error);
+ goto out;
/*
* Check for state resource limit exceeded.
*/
if ((new_stp->ls_flags & NFSLCK_LOCK) &&
- nfsrv_openpluslock > NFSRV_V4STATELIMIT)
- return (NFSERR_RESOURCE);
+ nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
+ error = NFSERR_RESOURCE;
+ goto out;
+ }
/*
* For the lock case, get another nfslock structure,
@@ -1546,14 +1569,7 @@ tryagain:
nfsrv_unlocklf(lfp);
}
NFSUNLOCKSTATE();
- if (other_lop)
- FREE((caddr_t)other_lop, M_NFSDLOCK);
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (error);
+ goto out;
}
/*
@@ -1582,15 +1598,7 @@ tryagain:
error = NFSERR_BADSTATEID;
}
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- /*
- * Called to lock or unlock, so the lock has gone away.
- */
- return (error);
+ goto out;
}
/*
@@ -1638,14 +1646,8 @@ tryagain:
nfsrv_unlocklf(lfp);
}
NFSUNLOCKSTATE();
- if (other_lop)
- FREE((caddr_t)other_lop, M_NFSDLOCK);
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (NFSERR_OPENMODE);
+ error = NFSERR_OPENMODE;
+ goto out;
}
} else
mystp = NULL;
@@ -1670,27 +1672,18 @@ tryagain:
}
if (ret == 0)
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
if (ret == 2)
- return (NFSERR_PERM);
+ error = NFSERR_PERM;
else
- return (NFSERR_OPENMODE);
+ error = NFSERR_OPENMODE;
+ goto out;
}
}
}
/* We're outta here */
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (0);
+ goto out;
}
}
@@ -1708,18 +1701,14 @@ tryagain:
lckstp = NULL;
goto tryagain;
}
- return (ret);
+ error = ret;
+ goto out;
}
if (!(new_stp->ls_flags & NFSLCK_CHECK) ||
(LIST_EMPTY(&lfp->lf_open) && LIST_EMPTY(&lfp->lf_lock) &&
LIST_EMPTY(&lfp->lf_deleg))) {
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (0);
+ goto out;
}
}
@@ -1773,7 +1762,8 @@ tryagain:
lckstp = NULL;
goto tryagain;
}
- return (ret);
+ error = ret;
+ goto out;
}
/* Never gets here. */
}
@@ -1801,12 +1791,7 @@ tryagain:
nfsrv_unlocklf(lfp);
}
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (0);
+ goto out;
}
/*
@@ -1877,12 +1862,7 @@ tryagain:
}
if (ret == 0)
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (error);
+ goto out;
}
}
}
@@ -1892,12 +1872,7 @@ tryagain:
*/
if (new_stp->ls_flags & (NFSLCK_TEST | NFSLCK_CHECK)) {
NFSUNLOCKSTATE();
- if (haslock) {
- NFSLOCKV4ROOTMUTEX();
- nfsv4_unlock(&nfsv4rootfs_lock, 1);
- NFSUNLOCKV4ROOTMUTEX();
- }
- return (0);
+ goto out;
}
/*
@@ -1950,6 +1925,8 @@ tryagain:
nfsrv_unlocklf(lfp);
}
NFSUNLOCKSTATE();
+
+out:
if (haslock) {
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 1);
@@ -1957,7 +1934,8 @@ tryagain:
}
if (other_lop)
FREE((caddr_t)other_lop, M_NFSDLOCK);
- return (0);
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1974,7 +1952,7 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
struct nfsclient *clp;
struct nfsstate *ownerstp;
struct nfslockfile *lfp, *new_lfp;
- int error, haslock = 0, ret, readonly = 0, getfhret = 0;
+ int error = 0, haslock = 0, ret, readonly = 0, getfhret = 0;
if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
readonly = 1;
@@ -1984,7 +1962,7 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
&new_stp->ls_stateid, 0);
if (error)
- return (error);
+ goto out;
/*
* Check for state resource limit exceeded.
@@ -1993,8 +1971,10 @@ nfsrv_opencheck(nfsquad_t clientid, nfsv4stateid_t *stateidp,
* returns NFSERR_RESOURCE and the limit is just a rather
* arbitrary high water mark, so no harm is done.
*/
- if (nfsrv_openpluslock > NFSRV_V4STATELIMIT)
- return (NFSERR_RESOURCE);
+ if (nfsrv_openpluslock > NFSRV_V4STATELIMIT) {
+ error = NFSERR_RESOURCE;
+ goto out;
+ }
tryagain:
MALLOC(new_lfp, struct nfslockfile *, sizeof (struct nfslockfile),
@@ -2052,7 +2032,7 @@ tryagain:
NFSUNLOCKV4ROOTMUTEX();
}
free((caddr_t)new_lfp, M_NFSDLOCKFILE);
- return (error);
+ goto out;
}
/*
@@ -2062,7 +2042,7 @@ tryagain:
if (vp == NULL) {
NFSUNLOCKSTATE();
FREE((caddr_t)new_lfp, M_NFSDLOCKFILE);
- return (0);
+ goto out;
}
/*
@@ -2082,7 +2062,7 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (error);
+ goto out;
}
/*
@@ -2113,7 +2093,8 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (NFSERR_EXPIRED);
+ error = NFSERR_EXPIRED;
+ goto out;
}
}
@@ -2148,7 +2129,7 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (error);
+ goto out;
}
}
@@ -2189,7 +2170,8 @@ tryagain:
*/
if (ret == -1)
goto tryagain;
- return (ret);
+ error = ret;
+ goto out;
}
}
stp = nstp;
@@ -2201,7 +2183,10 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (0);
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -2218,7 +2203,7 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
struct nfsstate *openstp = NULL, *new_open, *ownerstp, *new_deleg;
struct nfslockfile *lfp, *new_lfp;
struct nfsclient *clp;
- int error, haslock = 0, ret, delegate = 1, writedeleg = 1;
+ int error = 0, haslock = 0, ret, delegate = 1, writedeleg = 1;
int readonly = 0, cbret = 1, getfhret = 0;
if ((new_stp->ls_flags & NFSLCK_SHAREBITS) == NFSLCK_READACCESS)
@@ -2234,7 +2219,8 @@ nfsrv_openctrl(struct nfsrv_descript *nd, vnode_t vp,
if (error) {
printf("Nfsd: openctrl unexpected restart err=%d\n",
error);
- return (NFSERR_EXPIRED);
+ error = NFSERR_EXPIRED;
+ goto out;
}
tryagain:
@@ -2305,7 +2291,8 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (NFSERR_EXPIRED);
+ error = NFSERR_EXPIRED;
+ goto out;
}
if (new_stp->ls_flags & NFSLCK_RECLAIM)
@@ -2332,7 +2319,7 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (error);
+ goto out;
}
/*
@@ -2366,7 +2353,8 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (NFSERR_EXPIRED);
+ error = NFSERR_EXPIRED;
+ goto out;
}
/*
@@ -2431,7 +2419,7 @@ tryagain:
free((caddr_t)new_open, M_NFSDSTATE);
free((caddr_t)new_deleg, M_NFSDSTATE);
printf("nfsd openctrl unexpected client cnfl\n");
- return (error);
+ goto out;
}
}
}
@@ -2482,7 +2470,8 @@ tryagain:
openstp = NULL;
goto tryagain;
}
- return (ret);
+ error = ret;
+ goto out;
}
}
}
@@ -2855,6 +2844,9 @@ tryagain:
FREE((caddr_t)new_open, M_NFSDSTATE);
if (new_deleg)
FREE((caddr_t)new_deleg, M_NFSDSTATE);
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -2869,7 +2861,7 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
struct nfsclient *clp;
struct nfslockfile *lfp;
u_int32_t bits;
- int error, gotstate = 0, len = 0;
+ int error = 0, gotstate = 0, len = 0;
u_char client[NFSV4_OPAQUELIMIT];
/*
@@ -2878,7 +2870,7 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
&new_stp->ls_stateid, 0);
if (error)
- return (error);
+ goto out;
NFSLOCKSTATE();
/*
@@ -2925,7 +2917,7 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
nfsrv_nootherstate(stp))
nfsrv_freeopenowner(stp->ls_openowner, 0, p);
NFSUNLOCKSTATE();
- return (error);
+ goto out;
}
/*
@@ -2978,7 +2970,8 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
bits = (new_stp->ls_flags & NFSLCK_SHAREBITS);
if (~(stp->ls_flags) & bits) {
NFSUNLOCKSTATE();
- return (NFSERR_INVAL);
+ error = NFSERR_INVAL;
+ goto out;
}
stp->ls_flags = (bits | NFSLCK_OPEN);
stp->ls_stateid.seqid++;
@@ -2993,6 +2986,9 @@ nfsrv_openupdate(vnode_t vp, struct nfsstate *new_stp, nfsquad_t clientid,
nfsrv_writestable(client, len, NFSNST_NEWSTATE, p);
nfsrv_backupstable();
}
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3005,7 +3001,7 @@ nfsrv_delegupdate(nfsquad_t clientid, nfsv4stateid_t *stateidp,
{
struct nfsstate *stp;
struct nfsclient *clp;
- int error;
+ int error = 0;
fhandle_t fh;
/*
@@ -3014,7 +3010,7 @@ nfsrv_delegupdate(nfsquad_t clientid, nfsv4stateid_t *stateidp,
if (vp) {
error = nfsvno_getfh(vp, &fh, p);
if (error)
- return (error);
+ goto out;
}
/*
* Check for restart conditions (client and server).
@@ -3050,25 +3046,31 @@ nfsrv_delegupdate(nfsquad_t clientid, nfsv4stateid_t *stateidp,
*/
if (error == NFSERR_EXPIRED && op == NFSV4OP_DELEGPURGE) {
NFSUNLOCKSTATE();
- return (0);
+ error = 0;
+ goto out;
}
if (error) {
NFSUNLOCKSTATE();
- return (error);
+ goto out;
}
if (op == NFSV4OP_DELEGRETURN) {
if (NFSBCMP((caddr_t)&fh, (caddr_t)&stp->ls_lfp->lf_fh,
sizeof (fhandle_t))) {
NFSUNLOCKSTATE();
- return (NFSERR_BADSTATEID);
+ error = NFSERR_BADSTATEID;
+ goto out;
}
nfsrv_freedeleg(stp);
} else {
nfsrv_freedeleglist(&clp->lc_olddeleg);
}
NFSUNLOCKSTATE();
- return (0);
+ error = 0;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -3080,7 +3082,7 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
{
struct nfsstate *stp, *nstp, *openstp, *ownstp;
struct nfsclient *clp;
- int error;
+ int error = 0;
/*
* Check for restart conditions (client and server).
@@ -3088,7 +3090,7 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
error = nfsrv_checkrestart(clientid, new_stp->ls_flags,
&new_stp->ls_stateid, 0);
if (error)
- return (error);
+ goto out;
NFSLOCKSTATE();
/*
@@ -3098,7 +3100,7 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
(nfsquad_t)((u_quad_t)0), NULL, p);
if (error) {
NFSUNLOCKSTATE();
- return (error);
+ goto out;
}
LIST_FOREACH(ownstp, &clp->lc_open, ls_list) {
LIST_FOREACH(openstp, &ownstp->ls_open, ls_list) {
@@ -3116,7 +3118,8 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
nfsrv_freelockowner(stp, NULL, 0, p);
} else {
NFSUNLOCKSTATE();
- return (NFSERR_LOCKSHELD);
+ error = NFSERR_LOCKSHELD;
+ goto out;
}
}
stp = nstp;
@@ -3124,7 +3127,10 @@ nfsrv_releaselckown(struct nfsstate *new_stp, nfsquad_t clientid,
}
}
NFSUNLOCKSTATE();
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -3151,6 +3157,7 @@ nfsrv_getlockfh(vnode_t vp, u_short flags,
panic("nfsrv_getlockfh");
}
error = nfsvno_getfh(vp, fhp, p);
+ NFSEXITCODE(error);
return (error);
}
@@ -3406,6 +3413,7 @@ static int
nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
struct nfsstate *stp, struct nfsrvcache *op)
{
+ int error = 0;
if (op != nd->nd_rp)
panic("nfsrvstate checkseqid");
@@ -3421,20 +3429,27 @@ nfsrv_checkseqid(struct nfsrv_descript *nd, u_int32_t seqid,
stp->ls_op = op;
nfsrvd_refcache(op);
stp->ls_seq = seqid;
- return (0);
+ goto out;
} else if (stp->ls_seq == seqid && stp->ls_op &&
op->rc_xid == stp->ls_op->rc_xid &&
op->rc_refcnt == 0 &&
op->rc_reqlen == stp->ls_op->rc_reqlen &&
op->rc_cksum == stp->ls_op->rc_cksum) {
- if (stp->ls_op->rc_flag & RC_INPROG)
- return (NFSERR_DONTREPLY);
+ if (stp->ls_op->rc_flag & RC_INPROG) {
+ error = NFSERR_DONTREPLY;
+ goto out;
+ }
nd->nd_rp = stp->ls_op;
nd->nd_rp->rc_flag |= RC_INPROG;
nfsrvd_delcache(op);
- return (NFSERR_REPLYFROMCACHE);
+ error = NFSERR_REPLYFROMCACHE;
+ goto out;
}
- return (NFSERR_BADSEQID);
+ error = NFSERR_BADSEQID;
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -3558,6 +3573,7 @@ nfsrv_getclientipaddr(struct nfsrv_descript *nd, struct nfsclient *clp)
clp->lc_program = 0;
}
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -3590,7 +3606,7 @@ static int
nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
nfsv4stateid_t *stateidp, int specialid)
{
- int ret;
+ int ret = 0;
/*
* First check for a server restart. Open, LockT, ReleaseLockOwner
@@ -3598,11 +3614,15 @@ nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
*/
if (flags &
(NFSLCK_OPEN | NFSLCK_TEST | NFSLCK_RELEASE | NFSLCK_DELEGPURGE)) {
- if (clientid.lval[0] != nfsrvboottime)
- return (NFSERR_STALECLIENTID);
+ if (clientid.lval[0] != nfsrvboottime) {
+ ret = NFSERR_STALECLIENTID;
+ goto out;
+ }
} else if (stateidp->other[0] != nfsrvboottime &&
- specialid == 0)
- return (NFSERR_STALESTATEID);
+ specialid == 0) {
+ ret = NFSERR_STALESTATEID;
+ goto out;
+ }
/*
* Read, Write, Setattr and LockT can return NFSERR_GRACE and do
@@ -3610,11 +3630,14 @@ nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
* (The others will be checked, as required, later.)
*/
if (!(flags & (NFSLCK_CHECK | NFSLCK_TEST)))
- return (0);
+ goto out;
NFSLOCKSTATE();
ret = nfsrv_checkgrace(flags);
NFSUNLOCKSTATE();
+
+out:
+ NFSEXITCODE(ret);
return (ret);
}
@@ -3624,13 +3647,18 @@ nfsrv_checkrestart(nfsquad_t clientid, u_int32_t flags,
static int
nfsrv_checkgrace(u_int32_t flags)
{
+ int error = 0;
if (nfsrv_stablefirst.nsf_flags & NFSNSF_GRACEOVER) {
- if (flags & NFSLCK_RECLAIM)
- return (NFSERR_NOGRACE);
+ if (flags & NFSLCK_RECLAIM) {
+ error = NFSERR_NOGRACE;
+ goto out;
+ }
} else {
- if (!(flags & NFSLCK_RECLAIM))
- return (NFSERR_GRACE);
+ if (!(flags & NFSLCK_RECLAIM)) {
+ error = NFSERR_GRACE;
+ goto out;
+ }
/*
* If grace is almost over and we are still getting Reclaims,
@@ -3641,7 +3669,10 @@ nfsrv_checkgrace(u_int32_t flags)
nfsrv_stablefirst.nsf_eograce = NFSD_MONOSEC +
NFSRV_LEASEDELTA;
}
- return (0);
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -3790,6 +3821,8 @@ nfsrv_docallback(struct nfsclient *clp, int procnum,
} else {
NFSUNLOCKSTATE();
}
+
+ NFSEXITCODE(error);
return (error);
}
@@ -4096,10 +4129,10 @@ nfsrv_updatestable(NFSPROC_T *p)
NFSVNO_SETATTRVAL(&nva, size, 0);
vp = NFSFPVNODE(sf->nsf_fp);
vn_start_write(vp, &mp, V_WAIT);
- if (vn_lock(vp, LK_EXCLUSIVE) == 0) {
+ if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
error = nfsvno_setattr(vp, &nva, NFSFPCRED(sf->nsf_fp), p,
NULL);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
} else
error = EPERM;
vn_finished_write(mp);
@@ -4231,7 +4264,7 @@ nfsrv_checkstable(struct nfsclient *clp)
* Return 0 to indicate the conflict can't be revoked and 1 to indicate
* the revocation worked and the conflicting client is "bye, bye", so it
* can be tried again.
- * Return 2 to indicate that the vnode is VI_DOOMED after vn_lock().
+ * Return 2 to indicate that the vnode is VI_DOOMED after NFSVOPLOCK().
* Unlocks State before a non-zero value is returned.
*/
static int
@@ -4248,8 +4281,8 @@ nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
return (0);
if (*haslockp == 0) {
NFSUNLOCKSTATE();
- lktype = VOP_ISLOCKED(vp);
- VOP_UNLOCK(vp, 0);
+ lktype = NFSVOPISLOCKED(vp);
+ NFSVOPUNLOCK(vp, 0);
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsv4rootfs_lock);
do {
@@ -4258,7 +4291,7 @@ nfsrv_clientconflict(struct nfsclient *clp, int *haslockp, vnode_t vp,
} while (!gotlock);
NFSUNLOCKV4ROOTMUTEX();
*haslockp = 1;
- vn_lock(vp, lktype | LK_RETRY);
+ NFSVOPLOCK(vp, lktype | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) != 0)
return (2);
else
@@ -4317,7 +4350,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
if (clp->lc_delegtime < NFSD_MONOSEC) {
nfsrv_freedeleg(stp);
NFSUNLOCKSTATE();
- return (-1);
+ error = -1;
+ goto out;
}
NFSUNLOCKSTATE();
/*
@@ -4332,7 +4366,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (NFSERR_DELAY);
+ error = NFSERR_DELAY;
+ goto out;
}
/*
@@ -4388,7 +4423,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
retrycnt++;
} while ((error == NFSERR_BADSTATEID ||
error == NFSERR_BADHANDLE) && retrycnt < NFSV4_CBRETRYCNT);
- return (NFSERR_DELAY);
+ error = NFSERR_DELAY;
+ goto out;
}
if (clp->lc_expiry >= NFSD_MONOSEC &&
@@ -4404,7 +4440,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (NFSERR_DELAY);
+ error = NFSERR_DELAY;
+ goto out;
}
/*
@@ -4416,8 +4453,8 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
*/
if (*haslockp == 0) {
NFSUNLOCKSTATE();
- lktype = VOP_ISLOCKED(vp);
- VOP_UNLOCK(vp, 0);
+ lktype = NFSVOPISLOCKED(vp);
+ NFSVOPUNLOCK(vp, 0);
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsv4rootfs_lock);
do {
@@ -4426,15 +4463,17 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
} while (!gotlock);
NFSUNLOCKV4ROOTMUTEX();
*haslockp = 1;
- vn_lock(vp, lktype | LK_RETRY);
+ NFSVOPLOCK(vp, lktype | LK_RETRY);
if ((vp->v_iflag & VI_DOOMED) != 0) {
*haslockp = 0;
NFSLOCKV4ROOTMUTEX();
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
- return (NFSERR_PERM);
+ error = NFSERR_PERM;
+ goto out;
}
- return (-1);
+ error = -1;
+ goto out;
}
NFSUNLOCKSTATE();
@@ -4459,7 +4498,11 @@ nfsrv_delegconflict(struct nfsstate *stp, int *haslockp, NFSPROC_T *p,
}
if (zapped_clp)
nfsrv_zapclient(clp, p);
- return (-1);
+ error = -1;
+
+out:
+ NFSEXITCODE(error);
+ return (error);
}
/*
@@ -4491,8 +4534,8 @@ tryagain:
NFSUNLOCKV4ROOTMUTEX();
}
if (error == -1)
- return (0);
- return (error);
+ error = 0;
+ goto out;
}
/*
@@ -4511,7 +4554,7 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
- return (error);
+ goto out;
}
/*
@@ -4532,6 +4575,9 @@ tryagain:
nfsv4_unlock(&nfsv4rootfs_lock, 1);
NFSUNLOCKV4ROOTMUTEX();
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
@@ -4549,7 +4595,7 @@ nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
struct nfsclient *clp, int *haslockp, NFSPROC_T *p)
{
struct nfsstate *stp, *nstp;
- int ret;
+ int ret = 0;
stp = LIST_FIRST(&lfp->lf_deleg);
while (stp != LIST_END(&lfp->lf_deleg)) {
@@ -4561,12 +4607,14 @@ nfsrv_cleandeleg(vnode_t vp, struct nfslockfile *lfp,
* nfsrv_delegconflict() unlocks state
* when it returns non-zero.
*/
- return (ret);
+ goto out;
}
}
stp = nstp;
}
- return (0);
+out:
+ NFSEXITCODE(ret);
+ return (ret);
}
/*
@@ -4610,7 +4658,7 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
nfsrv_issuedelegs == 0)
return;
- KASSERT((VOP_ISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
+ KASSERT((NFSVOPISLOCKED(vp) != LK_EXCLUSIVE), ("vp %p is locked", vp));
/*
* First, get a reference on the nfsv4rootfs_lock so that an
* exclusive lock cannot be acquired by another thread.
@@ -4626,9 +4674,9 @@ nfsd_recalldelegation(vnode_t vp, NFSPROC_T *p)
NFSGETNANOTIME(&mytime);
starttime = (u_int32_t)mytime.tv_sec;
do {
- if (vn_lock(vp, LK_EXCLUSIVE) == 0) {
+ if (NFSVOPLOCK(vp, LK_EXCLUSIVE) == 0) {
error = nfsrv_checkremove(vp, 0, p);
- VOP_UNLOCK(vp, 0);
+ NFSVOPUNLOCK(vp, 0);
} else
error = EPERM;
if (error == NFSERR_DELAY) {
@@ -4700,7 +4748,7 @@ nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
NFSISSET_ATTRBIT(attrbitp, NFSATTRBIT_ACL))
stp->ls_flags |= NFSLCK_SETATTR;
if (stp->ls_flags == 0)
- return (0);
+ goto out;
lop->lo_end = NFS64BITSSET;
lop->lo_flags = NFSLCK_WRITE;
stp->ls_ownerlen = 0;
@@ -4712,6 +4760,9 @@ nfsrv_checksetattr(vnode_t vp, struct nfsrv_descript *nd,
stp->ls_stateid.other[2] = stateidp->other[2];
error = nfsrv_lockctrl(vp, &stp, &lop, NULL, clientid,
stateidp, exp, nd, p);
+
+out:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -4731,13 +4782,13 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
struct nfsclient *clp;
struct nfsvattr nva;
fhandle_t nfh;
- int error;
+ int error = 0;
nfsattrbit_t cbbits;
u_quad_t delegfilerev;
NFSCBGETATTR_ATTRBIT(attrbitp, &cbbits);
if (!NFSNONZERO_ATTRBIT(&cbbits))
- return (0);
+ goto out;
/*
* Get the lock file structure.
@@ -4750,8 +4801,8 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
if (error) {
NFSUNLOCKSTATE();
if (error == -1)
- return (0);
- return (error);
+ error = 0;
+ goto out;
}
/*
@@ -4763,7 +4814,7 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
}
if (stp == LIST_END(&lfp->lf_deleg)) {
NFSUNLOCKSTATE();
- return (0);
+ goto out;
}
clp = stp->ls_clp;
delegfilerev = stp->ls_filerev;
@@ -4783,7 +4834,7 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
clp->lc_clientid.qval == nd->nd_clientid.qval) ||
nfsaddr2_match(clp->lc_req.nr_nam, nd->nd_nam)) {
NFSUNLOCKSTATE();
- return (0);
+ goto out;
}
/*
@@ -4814,7 +4865,11 @@ nfsrv_checkgetattr(struct nfsrv_descript *nd, vnode_t vp,
} else {
NFSUNLOCKSTATE();
}
- return (0);
+ error = 0;
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -4997,6 +5052,8 @@ nfsrv_locallock(vnode_t vp, struct nfslockfile *lfp, int flags,
/* handle fragment past end of list */
error = nfsrv_dolocal(vp, lfp, flags, NFSLCK_UNLOCK, first,
end, cfp, p);
+
+ NFSEXITCODE(error);
return (error);
}
@@ -5079,7 +5136,7 @@ nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
uint64_t first, uint64_t end, struct nfslockconflict *cfp, NFSPROC_T *p)
{
struct nfsrollback *rlp;
- int error, ltype, oldltype;
+ int error = 0, ltype, oldltype;
if (flags & NFSLCK_WRITE)
ltype = F_WRLCK;
@@ -5095,7 +5152,7 @@ nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
oldltype = F_UNLCK;
if (ltype == oldltype || (oldltype == F_WRLCK && ltype == F_RDLCK))
/* nothing to do */
- return (0);
+ goto out;
error = nfsvno_advlock(vp, ltype, first, end, p);
if (error != 0) {
if (cfp != NULL) {
@@ -5116,6 +5173,9 @@ nfsrv_dolocal(vnode_t vp, struct nfslockfile *lfp, int flags, int oldflags,
rlp->rlck_type = oldltype;
LIST_INSERT_HEAD(&lfp->lf_rollback, rlp, rlck_list);
}
+
+out:
+ NFSEXITCODE(error);
return (error);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index 252eb0d..bd92c3f 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -1418,21 +1418,23 @@ nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
if (len == 0 && nfs_pubfhset && (nd->nd_flag & ND_NFSV3) &&
nd->nd_procnum == NFSPROC_LOOKUP) {
nd->nd_flag |= ND_PUBLOOKUP;
- return (0);
+ goto nfsmout;
}
if (len < NFSRV_MINFH || len > NFSRV_MAXFH) {
if (nd->nd_flag & ND_NFSV4) {
if (len > 0 && len <= NFSX_V4FHMAX) {
error = nfsm_advance(nd, NFSM_RNDUP(len), -1);
if (error)
- return (error);
+ goto nfsmout;
nd->nd_repstat = NFSERR_BADHANDLE;
- return (0);
+ goto nfsmout;
} else {
- return (EBADRPC);
+ error = EBADRPC;
+ goto nfsmout;
}
} else {
- return (EBADRPC);
+ error = EBADRPC;
+ goto nfsmout;
}
}
copylen = len;
@@ -1450,11 +1452,12 @@ nfsrv_mtofh(struct nfsrv_descript *nd, struct nfsrvfh *fhp)
nd->nd_procnum == NFSPROC_LOOKUP &&
!NFSBCMP((caddr_t)tl, nfs_v2pubfh, NFSX_V2FH)) {
nd->nd_flag |= ND_PUBLOOKUP;
- return (0);
+ goto nfsmout;
}
NFSBCOPY(tl, (caddr_t)fhp->nfsrvfh_data, copylen);
fhp->nfsrvfh_len = copylen;
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
@@ -1503,22 +1506,28 @@ nfsd_errmap(struct nfsrv_descript *nd)
APPLESTATIC int
nfsrv_checkuidgid(struct nfsrv_descript *nd, struct nfsvattr *nvap)
{
+ int error = 0;
/*
* If not setting either uid nor gid, it's OK.
*/
if (NFSVNO_NOTSETUID(nvap) && NFSVNO_NOTSETGID(nvap))
- return (0);
+ goto out;
if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid == nfsrv_defaultuid)
- || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid))
- return (NFSERR_BADOWNER);
+ || (NFSVNO_ISSETGID(nvap) && nvap->na_gid == nfsrv_defaultgid)) {
+ error = NFSERR_BADOWNER;
+ goto out;
+ }
if (nd->nd_cred->cr_uid == 0)
- return (0);
+ goto out;
if ((NFSVNO_ISSETUID(nvap) && nvap->na_uid != nd->nd_cred->cr_uid) ||
(NFSVNO_ISSETGID(nvap) && nvap->na_gid != nd->nd_cred->cr_gid &&
!groupmember(nvap->na_gid, nd->nd_cred)))
- return (NFSERR_PERM);
- return (0);
+ error = NFSERR_PERM;
+
+out:
+ NFSEXITCODE2(error, nd);
+ return (error);
}
/*
@@ -1542,7 +1551,7 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
* the V2 and 3 semantics.
*/
if ((nd->nd_flag & ND_NFSV4) == 0)
- return;
+ goto out;
NFSVNO_ATTRINIT(&nva);
NFSZERO_ATTRBIT(&nattrbits);
tuid = nd->nd_cred->cr_uid;
@@ -1604,6 +1613,9 @@ nfsrv_fixattr(struct nfsrv_descript *nd, vnode_t vp,
#endif
NFSCLRBIT_ATTRBIT(attrbitp, NFSATTRBIT_ACL);
nd->nd_cred->cr_uid = tuid;
+
+out:
+ NFSEXITCODE2(0, nd);
}
/*
@@ -1800,10 +1812,12 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
len = fxdr_unsigned(int, *tl);
if (len > NFS_MAXNAMLEN) {
nd->nd_repstat = NFSERR_NAMETOL;
- return (0);
+ error = 0;
+ goto nfsmout;
} else if (len <= 0) {
nd->nd_repstat = NFSERR_INVAL;
- return (0);
+ error = 0;
+ goto nfsmout;
}
/*
@@ -1815,14 +1829,17 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
for (i = 0; i < len; i++) {
while (rem == 0) {
md = mbuf_next(md);
- if (md == NULL)
- return (EBADRPC);
+ if (md == NULL) {
+ error = EBADRPC;
+ goto nfsmout;
+ }
fromcp = NFSMTOD(md, caddr_t);
rem = mbuf_len(md);
}
if (*fromcp == '\0') {
nd->nd_repstat = EACCES;
- return (0);
+ error = 0;
+ goto nfsmout;
}
/*
* For lookups on the public filehandle, do some special
@@ -1858,7 +1875,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
*/
if (*fromcp == '/' && pubtype != 1) {
nd->nd_repstat = EACCES;
- return (0);
+ error = 0;
+ goto nfsmout;
}
/*
@@ -1871,7 +1889,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
digit = nfsrv_hexdigit(*fromcp, &error);
if (error) {
nd->nd_repstat = EACCES;
- return (0);
+ error = 0;
+ goto nfsmout;
}
if (percent == 1) {
val = (digit << 4);
@@ -1890,7 +1909,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
*/
if ((len - i) < 3) {
nd->nd_repstat = EACCES;
- return (0);
+ error = 0;
+ goto nfsmout;
}
percent = 1;
} else {
@@ -1908,7 +1928,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
nd->nd_repstat = NFSERR_BADNAME;
else
nd->nd_repstat = EACCES;
- return (0);
+ error = 0;
+ goto nfsmout;
}
hash += ((u_char)*fromcp);
*tocp++ = *fromcp;
@@ -1926,7 +1947,7 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
} else {
error = nfsm_advance(nd, i, rem);
if (error)
- return (error);
+ goto nfsmout;
}
}
@@ -1939,11 +1960,13 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
(outlen == 2 && bufp[0] == '.' &&
bufp[1] == '.')) {
nd->nd_repstat = NFSERR_BADNAME;
- return (0);
+ error = 0;
+ goto nfsmout;
}
if (nfsrv_checkutf8((u_int8_t *)bufp, outlen)) {
nd->nd_repstat = NFSERR_INVAL;
- return (0);
+ error = 0;
+ goto nfsmout;
}
}
}
@@ -1952,6 +1975,7 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
if (hashp != NULL)
*hashp = hash;
nfsmout:
+ NFSEXITCODE2(error, nd);
return (error);
}
diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c
index f58f7de..bebc8ee 100644
--- a/sys/fs/smbfs/smbfs_smb.c
+++ b/sys/fs/smbfs/smbfs_smb.c
@@ -556,7 +556,7 @@ smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime,
/*
* Set DOS file attributes.
- * Looks like this call can be used only if CAP_NT_SMBS bit is on.
+ * Looks like this call can be used only if SMB_CAP_NT_SMBS bit is on.
*/
int
smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index 5a07a45..e9324cf 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -926,7 +926,7 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize)
if (newpages < oldpages) {
swap_pager_freespace(uobj, newpages, oldpages -
newpages);
- vm_object_page_remove(uobj, newpages, 0, FALSE);
+ vm_object_page_remove(uobj, newpages, 0, 0);
}
/*
OpenPOWER on IntegriCloud