diff options
Diffstat (limited to 'sys/fs')
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); } /* |