summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver/nfs_srvsubs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfsserver/nfs_srvsubs.c')
-rw-r--r--sys/nfsserver/nfs_srvsubs.c133
1 files changed, 97 insertions, 36 deletions
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 9da4b1a..7217150 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -85,8 +85,8 @@ u_int32_t nfsrv_rpc_call, nfsrv_rpc_vers, nfsrv_rpc_reply,
u_int32_t nfsrv_nfs_prog, nfsrv_nfs_true, nfsrv_nfs_false;
/* And other global data */
-static nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK,
- NFNON, NFCHR, NFNON };
+static const nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR,
+ NFLNK, NFNON, NFCHR, NFNON };
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))])
#define vtonfsv3_mode(m) txdr_unsigned((m) & ALLPERMS)
@@ -100,10 +100,12 @@ int nfsd_head_flag;
static int nfs_prev_nfssvc_sy_narg;
static sy_call_t *nfs_prev_nfssvc_sy_call;
+struct mtx nfsd_mtx;
+
/*
* Mapping of old NFS Version 2 RPC numbers to generic numbers.
*/
-int nfsrv_nfsv3_procid[NFS_NPROCS] = {
+const int nfsrv_nfsv3_procid[NFS_NPROCS] = {
NFSPROC_NULL,
NFSPROC_GETATTR,
NFSPROC_SETATTR,
@@ -132,7 +134,7 @@ int nfsrv_nfsv3_procid[NFS_NPROCS] = {
/*
* and the reverse mapping from generic to Version 2 procedure numbers
*/
-int nfsrvv2_procid[NFS_NPROCS] = {
+const int nfsrvv2_procid[NFS_NPROCS] = {
NFSV2PROC_NULL,
NFSV2PROC_GETATTR,
NFSV2PROC_SETATTR,
@@ -163,7 +165,7 @@ int nfsrvv2_procid[NFS_NPROCS] = {
* Use 0 (which gets converted to NFSERR_IO) as the catch all for ones not
* specifically defined in RFC 1094.
*/
-static u_char nfsrv_v2errmap[ELAST] = {
+static const u_char nfsrv_v2errmap[ELAST] = {
NFSERR_PERM, NFSERR_NOENT, 0, 0, 0,
NFSERR_NXIO, 0, 0, 0, 0,
0, 0, NFSERR_ACCES, 0, 0,
@@ -192,12 +194,12 @@ static u_char nfsrv_v2errmap[ELAST] = {
* The first entry is the default error return and the rest are the valid
* errors for that RPC in increasing numeric order.
*/
-static short nfsv3err_null[] = {
+static const short nfsv3err_null[] = {
0,
0,
};
-static short nfsv3err_getattr[] = {
+static const short nfsv3err_getattr[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_STALE,
@@ -206,7 +208,7 @@ static short nfsv3err_getattr[] = {
0,
};
-static short nfsv3err_setattr[] = {
+static const short nfsv3err_setattr[] = {
NFSERR_IO,
NFSERR_PERM,
NFSERR_IO,
@@ -222,7 +224,7 @@ static short nfsv3err_setattr[] = {
0,
};
-static short nfsv3err_lookup[] = {
+static const short nfsv3err_lookup[] = {
NFSERR_IO,
NFSERR_NOENT,
NFSERR_IO,
@@ -235,7 +237,7 @@ static short nfsv3err_lookup[] = {
0,
};
-static short nfsv3err_access[] = {
+static const short nfsv3err_access[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_STALE,
@@ -244,7 +246,7 @@ static short nfsv3err_access[] = {
0,
};
-static short nfsv3err_readlink[] = {
+static const short nfsv3err_readlink[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -256,7 +258,7 @@ static short nfsv3err_readlink[] = {
0,
};
-static short nfsv3err_read[] = {
+static const short nfsv3err_read[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_NXIO,
@@ -268,7 +270,7 @@ static short nfsv3err_read[] = {
0,
};
-static short nfsv3err_write[] = {
+static const short nfsv3err_write[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -283,7 +285,7 @@ static short nfsv3err_write[] = {
0,
};
-static short nfsv3err_create[] = {
+static const short nfsv3err_create[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -300,7 +302,7 @@ static short nfsv3err_create[] = {
0,
};
-static short nfsv3err_mkdir[] = {
+static const short nfsv3err_mkdir[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -317,7 +319,7 @@ static short nfsv3err_mkdir[] = {
0,
};
-static short nfsv3err_symlink[] = {
+static const short nfsv3err_symlink[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -334,7 +336,7 @@ static short nfsv3err_symlink[] = {
0,
};
-static short nfsv3err_mknod[] = {
+static const short nfsv3err_mknod[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -352,7 +354,7 @@ static short nfsv3err_mknod[] = {
0,
};
-static short nfsv3err_remove[] = {
+static const short nfsv3err_remove[] = {
NFSERR_IO,
NFSERR_NOENT,
NFSERR_IO,
@@ -366,7 +368,7 @@ static short nfsv3err_remove[] = {
0,
};
-static short nfsv3err_rmdir[] = {
+static const short nfsv3err_rmdir[] = {
NFSERR_IO,
NFSERR_NOENT,
NFSERR_IO,
@@ -384,7 +386,7 @@ static short nfsv3err_rmdir[] = {
0,
};
-static short nfsv3err_rename[] = {
+static const short nfsv3err_rename[] = {
NFSERR_IO,
NFSERR_NOENT,
NFSERR_IO,
@@ -407,7 +409,7 @@ static short nfsv3err_rename[] = {
0,
};
-static short nfsv3err_link[] = {
+static const short nfsv3err_link[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -427,7 +429,7 @@ static short nfsv3err_link[] = {
0,
};
-static short nfsv3err_readdir[] = {
+static const short nfsv3err_readdir[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -440,7 +442,7 @@ static short nfsv3err_readdir[] = {
0,
};
-static short nfsv3err_readdirplus[] = {
+static const short nfsv3err_readdirplus[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_ACCES,
@@ -454,7 +456,7 @@ static short nfsv3err_readdirplus[] = {
0,
};
-static short nfsv3err_fsstat[] = {
+static const short nfsv3err_fsstat[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_STALE,
@@ -463,7 +465,7 @@ static short nfsv3err_fsstat[] = {
0,
};
-static short nfsv3err_fsinfo[] = {
+static const short nfsv3err_fsinfo[] = {
NFSERR_STALE,
NFSERR_STALE,
NFSERR_BADHANDLE,
@@ -471,7 +473,7 @@ static short nfsv3err_fsinfo[] = {
0,
};
-static short nfsv3err_pathconf[] = {
+static const short nfsv3err_pathconf[] = {
NFSERR_STALE,
NFSERR_STALE,
NFSERR_BADHANDLE,
@@ -479,7 +481,7 @@ static short nfsv3err_pathconf[] = {
0,
};
-static short nfsv3err_commit[] = {
+static const short nfsv3err_commit[] = {
NFSERR_IO,
NFSERR_IO,
NFSERR_STALE,
@@ -488,7 +490,7 @@ static short nfsv3err_commit[] = {
0,
};
-static short *nfsrv_v3errmap[] = {
+static const short *nfsrv_v3errmap[] = {
nfsv3err_null,
nfsv3err_getattr,
nfsv3err_setattr,
@@ -520,8 +522,11 @@ static int
nfsrv_modevent(module_t mod, int type, void *data)
{
+ NET_LOCK_GIANT();
+
switch (type) {
case MOD_LOAD:
+ mtx_init(&nfsd_mtx, "nfsd_mtx", NULL, MTX_DEF);
nfsrv_rpc_vers = txdr_unsigned(RPC_VER2);
nfsrv_rpc_call = txdr_unsigned(RPC_CALL);
nfsrv_rpc_reply = txdr_unsigned(RPC_REPLY);
@@ -538,10 +543,11 @@ nfsrv_modevent(module_t mod, int type, void *data)
if (nfsrv_ticks < 1)
nfsrv_ticks = 1;
- nfsrv_init(0); /* Init server data structures */
nfsrv_initcache(); /* Init the server request cache */
-
+ NFSD_LOCK();
+ nfsrv_init(0); /* Init server data structures */
callout_init(&nfsrv_callout, 0);
+ NFSD_UNLOCK();
nfsrv_timer(0);
nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg;
@@ -557,8 +563,10 @@ nfsrv_modevent(module_t mod, int type, void *data)
callout_stop(&nfsrv_callout);
sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg;
sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call;
+ mtx_destroy(&nfsd_mtx);
break;
}
+ NET_UNLOCK_GIANT();
return 0;
}
static moduledata_t nfsserver_mod = {
@@ -603,6 +611,10 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
struct componentname *cnp = &ndp->ni_cnd;
int lockleaf = (cnp->cn_flags & LOCKLEAF) != 0;
+ NFSD_LOCK_ASSERT();
+ NFSD_UNLOCK();
+ mtx_lock(&Giant); /* VFS */
+
*retdirp = NULL;
cnp->cn_flags |= NOMACCHECK;
cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
@@ -646,8 +658,12 @@ nfs_namei(struct nameidata *ndp, fhandle_t *fhp, int len,
/*
* Extract and set starting directory.
*/
+ mtx_unlock(&Giant); /* VFS */
+ NFSD_LOCK();
error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
nam, &rdonly, pubflag);
+ NFSD_UNLOCK();
+ mtx_lock(&Giant); /* VFS */
if (error)
goto out;
if (dp->v_type != VDIR) {
@@ -868,6 +884,8 @@ out:
} else if ((ndp->ni_cnd.cn_flags & (WANTPARENT|LOCKPARENT)) == 0) {
ndp->ni_dvp = NULL;
}
+ mtx_unlock(&Giant); /* VFS */
+ NFSD_LOCK();
return (error);
}
@@ -882,6 +900,8 @@ nfsm_adj(struct mbuf *mp, int len, int nul)
int count, i;
char *cp;
+ NFSD_LOCK_DONTCARE();
+
/*
* Trim from tail. Scan the mbuf chain,
* calculating its length and finding the last mbuf.
@@ -1043,6 +1063,8 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
struct sockaddr_int *saddr;
#endif
+ NFSD_LOCK_ASSERT();
+
*vpp = NULL;
if (nfs_ispublicfh(fhp)) {
@@ -1054,12 +1076,14 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
mp = vfs_getvfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
+ NFSD_UNLOCK();
+ mtx_lock(&Giant); /* VFS */
error = VFS_CHECKEXP(mp, nam, &exflags, &credanon);
if (error)
- return (error);
+ goto out;
error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
if (error)
- return (error);
+ goto out;
#ifdef MNT_EXNORESPORT
if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) {
saddr = (struct sockaddr_in *)nam;
@@ -1069,7 +1093,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
ntohs(saddr->sin_port) >= IPPORT_RESERVED) {
vput(*vpp);
*vpp = NULL;
- return (NFSERR_AUTHERR | AUTH_TOOWEAK);
+ error = NFSERR_AUTHERR | AUTH_TOOWEAK;
}
}
#endif
@@ -1091,7 +1115,10 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp,
if (!lockflag)
VOP_UNLOCK(*vpp, 0, td);
- return (0);
+out:
+ mtx_unlock(&Giant); /* VFS */
+ NFSD_LOCK();
+ return (error);
}
@@ -1106,6 +1133,8 @@ nfs_ispublicfh(fhandle_t *fhp)
char *cp = (char *)fhp;
int i;
+ NFSD_LOCK_DONTCARE();
+
for (i = 0; i < NFSX_V3FH; i++)
if (*cp++ != 0)
return (FALSE);
@@ -1124,6 +1153,8 @@ netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
{
struct sockaddr_in *inetaddr;
+ NFSD_LOCK_DONTCARE();
+
switch (family) {
case AF_INET:
inetaddr = (struct sockaddr_in *)nam;
@@ -1159,9 +1190,11 @@ netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
int
nfsrv_errmap(struct nfsrv_descript *nd, int err)
{
- short *defaulterrp, *errp;
+ const short *defaulterrp, *errp;
int e;
+ NFSD_LOCK_DONTCARE();
+
if (nd->nd_flag & ND_NFSV3) {
if (nd->nd_procnum <= NFSPROC_COMMIT) {
errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
@@ -1187,6 +1220,9 @@ int
nfsrv_object_create(struct vnode *vp)
{
+ GIANT_REQUIRED;
+ NFSD_UNLOCK_ASSERT();
+
if (vp == NULL || vp->v_type != VREG)
return (1);
return (vfs_object_create(vp, curthread, curthread->td_ucred));
@@ -1203,6 +1239,8 @@ nfsrvw_sort(gid_t *list, int num)
int i, j;
gid_t v;
+ NFSD_LOCK_DONTCARE();
+
/* Insertion sort. */
for (i = 1; i < num; i++) {
v = list[i];
@@ -1221,6 +1259,8 @@ nfsrv_setcred(struct ucred *incred, struct ucred *outcred)
{
int i;
+ NFSD_LOCK_DONTCARE();
+
bzero((caddr_t)outcred, sizeof (struct ucred));
outcred->cr_ref = 1;
outcred->cr_uid = incred->cr_uid;
@@ -1239,6 +1279,8 @@ nfsm_srvfhtom_xx(fhandle_t *f, int v3, struct mbuf **mb, caddr_t *bpos)
{
u_int32_t *tl;
+ NFSD_LOCK_DONTCARE();
+
if (v3) {
tl = nfsm_build_xx(NFSX_UNSIGNED + NFSX_V3FH, mb, bpos);
*tl++ = txdr_unsigned(NFSX_V3FH);
@@ -1265,6 +1307,8 @@ nfsm_srvstrsiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
+ NFSD_LOCK_DONTCARE();
+
tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
@@ -1279,6 +1323,8 @@ nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
+ NFSD_LOCK_DONTCARE();
+
tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
@@ -1292,15 +1338,26 @@ nfsm_srvnamesiz_xx(int *s, int m, struct mbuf **md, caddr_t *dpos)
void
nfsm_clget_xx(u_int32_t **tl, struct mbuf *mb, struct mbuf **mp,
- char **bp, char **be, caddr_t bpos)
+ char **bp, char **be, caddr_t bpos, int droplock)
{
struct mbuf *nmp;
+ NFSD_LOCK_DONTCARE();
+
+ if (droplock)
+ NFSD_LOCK_ASSERT();
+ else
+ NFSD_UNLOCK_ASSERT();
+
if (*bp >= *be) {
if (*mp == mb)
(*mp)->m_len += *bp - bpos;
+ if (droplock)
+ NFSD_UNLOCK();
MGET(nmp, M_TRYWAIT, MT_DATA);
MCLGET(nmp, M_TRYWAIT);
+ if (droplock)
+ NFSD_LOCK();
nmp->m_len = NFSMSIZ(nmp);
(*mp)->m_next = nmp;
*mp = nmp;
@@ -1317,6 +1374,8 @@ nfsm_srvmtofh_xx(fhandle_t *f, struct nfsrv_descript *nfsd, struct mbuf **md,
u_int32_t *tl;
int fhlen;
+ NFSD_LOCK_DONTCARE();
+
if (nfsd->nd_flag & ND_NFSV3) {
tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
@@ -1343,6 +1402,8 @@ nfsm_srvsattr_xx(struct vattr *a, struct mbuf **md, caddr_t *dpos)
{
u_int32_t *tl;
+ NFSD_LOCK_DONTCARE();
+
tl = nfsm_dissect_xx(NFSX_UNSIGNED, md, dpos);
if (tl == NULL)
return EBADRPC;
OpenPOWER on IntegriCloud