/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* FreeBSD-Id: nfs_serv.c,v 1.52 1997/10/28 15:59:05 bde Exp $
*/
+#include <nfs/nfs_conf.h>
+#if CONFIG_NFS_SERVER
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <security/mac_framework.h>
#endif
-#if NFSSERVER
-
/*
* NFS server globals
*/
int nfsd_thread_count = 0;
int nfsd_thread_max = 0;
-lck_grp_t *nfsd_lck_grp;
-lck_mtx_t *nfsd_mutex;
+static LCK_GRP_DECLARE(nfsd_lck_grp, "nfsd");
+LCK_MTX_DECLARE(nfsd_mutex, &nfsd_lck_grp);
struct nfsd_head nfsd_head, nfsd_queue;
-lck_grp_t *nfsrv_slp_rwlock_group;
-lck_grp_t *nfsrv_slp_mutex_group;
+LCK_GRP_DECLARE(nfsrv_slp_rwlock_group, "nfsrv-slp-rwlock");
+LCK_GRP_DECLARE(nfsrv_slp_mutex_group, "nfsrv-slp-mutex");
struct nfsrv_sockhead nfsrv_socklist, nfsrv_sockwg,
nfsrv_sockwait, nfsrv_sockwork;
struct nfsrv_sock *nfsrv_udpsock = NULL;
struct nfsrv_export_hashhead *nfsrv_export_hashtbl = NULL;
int nfsrv_export_hash_size = NFSRVEXPHASHSZ;
u_long nfsrv_export_hash;
-lck_grp_t *nfsrv_export_rwlock_group;
-lck_rw_t nfsrv_export_rwlock;
+static LCK_GRP_DECLARE(nfsrv_export_rwlock_group, "nfsrv-export-rwlock");
+LCK_RW_DECLARE(nfsrv_export_rwlock, &nfsrv_export_rwlock_group);
#if CONFIG_FSE
/* NFS server file modification event generator */
struct nfsrv_fmod_hashhead *nfsrv_fmod_hashtbl;
u_long nfsrv_fmod_hash;
-lck_grp_t *nfsrv_fmod_grp;
-lck_mtx_t *nfsrv_fmod_mutex;
+static LCK_GRP_DECLARE(nfsrv_fmod_grp, "nfsrv_fmod");
+LCK_MTX_DECLARE(nfsrv_fmod_mutex, &nfsrv_fmod_grp);
static int nfsrv_fmod_timer_on = 0;
int nfsrv_fsevents_enabled = 1;
#endif
uint32_t nfsrv_user_stat_node_count = 0;
uint32_t nfsrv_user_stat_max_idle_sec = NFSRV_USER_STAT_DEF_IDLE_SEC;
uint32_t nfsrv_user_stat_max_nodes = NFSRV_USER_STAT_DEF_MAX_NODES;
-lck_grp_t *nfsrv_active_user_mutex_group;
+LCK_GRP_DECLARE(nfsrv_active_user_mutex_group, "nfs-active-user-mutex");
int nfsrv_wg_delay = NFSRV_WGATHERDELAY * 1000;
int nfsrv_wg_delay_v3 = 0;
printf("struct nfsrv_sock bloated (> %dbytes)\n", NFS_SVCALLOC);
}
- /* init nfsd mutex */
- nfsd_lck_grp = lck_grp_alloc_init("nfsd", LCK_GRP_ATTR_NULL);
- nfsd_mutex = lck_mtx_alloc_init(nfsd_lck_grp, LCK_ATTR_NULL);
-
- /* init slp rwlock */
- nfsrv_slp_rwlock_group = lck_grp_alloc_init("nfsrv-slp-rwlock", LCK_GRP_ATTR_NULL);
- nfsrv_slp_mutex_group = lck_grp_alloc_init("nfsrv-slp-mutex", LCK_GRP_ATTR_NULL);
-
/* init export data structures */
LIST_INIT(&nfsrv_exports);
- nfsrv_export_rwlock_group = lck_grp_alloc_init("nfsrv-export-rwlock", LCK_GRP_ATTR_NULL);
- lck_rw_init(&nfsrv_export_rwlock, nfsrv_export_rwlock_group, LCK_ATTR_NULL);
-
- /* init active user list mutex structures */
- nfsrv_active_user_mutex_group = lck_grp_alloc_init("nfs-active-user-mutex", LCK_GRP_ATTR_NULL);
-
- /* init nfs server request cache mutex */
- nfsrv_reqcache_lck_grp = lck_grp_alloc_init("nfsrv_reqcache", LCK_GRP_ATTR_NULL);
- nfsrv_reqcache_mutex = lck_mtx_alloc_init(nfsrv_reqcache_lck_grp, LCK_ATTR_NULL);
#if CONFIG_FSE
/* init NFS server file modified event generation */
nfsrv_fmod_hashtbl = hashinit(NFSRVFMODHASHSZ, M_TEMP, &nfsrv_fmod_hash);
- nfsrv_fmod_grp = lck_grp_alloc_init("nfsrv_fmod", LCK_GRP_ATTR_NULL);
- nfsrv_fmod_mutex = lck_mtx_alloc_init(nfsrv_fmod_grp, LCK_ATTR_NULL);
#endif
/* initialize NFS server timer callouts */
mbuf_t *mrepp)
{
int error, attrerr, mreadcnt;
- uint32_t reqlen, maxlen, count, len, tlen, left;
+ uint32_t reqlen, maxlen, count, len, tlen;
mbuf_t mread, m;
vnode_t vp;
struct nfs_filehandle nfh;
- struct nfs_export *nx;
+ struct nfs_export *nx = NULL;
struct nfs_export_options *nxo;
uio_t auio = NULL;
char *uio_bufp = NULL;
if ((u_quad_t)off >= vap->va_data_size) {
count = 0;
} else if (((u_quad_t)off + reqlen) > vap->va_data_size) {
- count = nfsm_rndup(vap->va_data_size - off);
+ count = (int)nfsm_rndup(vap->va_data_size - off);
} else {
count = reqlen;
}
- len = left = count;
+ len = count;
if (count > 0) {
/* get mbuf list to hold read data */
error = nfsm_mbuf_get_list(count, &mread, &mreadcnt);
struct nfsrv_fmod_hashhead *headp, firehead;
struct nfsrv_fmod *fp, *nfp, *pfp;
uint64_t timenow, next_deadline;
- int interval = 0, i, fmod_fire;
+ time_t interval = 0;
+ int i, fmod_fire;
LIST_INIT(&firehead);
- lck_mtx_lock(nfsrv_fmod_mutex);
+ lck_mtx_lock(&nfsrv_fmod_mutex);
again:
clock_get_uptime(&timenow);
clock_interval_to_deadline(nfsrv_fmod_pendtime, 1000 * 1000,
}
if (fmod_fire) {
- lck_mtx_unlock(nfsrv_fmod_mutex);
+ lck_mtx_unlock(&nfsrv_fmod_mutex);
/*
* Fire off the content modified fsevent for each
* entry and free it.
LIST_REMOVE(fp, fm_link);
FREE(fp, M_TEMP);
}
- lck_mtx_lock(nfsrv_fmod_mutex);
+ lck_mtx_lock(&nfsrv_fmod_mutex);
nfsrv_fmod_pending -= fmod_fire;
goto again;
}
* entry is ready to send its fsevent.
*/
if (nfsrv_fmod_pending > 0) {
- interval = (next_deadline - timenow) / (1000 * 1000);
+ interval = ((time_t)(next_deadline - timenow)) / (1000 * 1000);
if (interval < nfsrv_fmod_min_interval) {
interval = nfsrv_fmod_min_interval;
}
nfs_interval_timer_start(nfsrv_fmod_timer_call, interval);
}
- lck_mtx_unlock(nfsrv_fmod_mutex);
+ lck_mtx_unlock(&nfsrv_fmod_mutex);
}
/*
struct nfsrv_fmod *fp;
struct nfsrv_fmod_hashhead *head;
- lck_mtx_lock(nfsrv_fmod_mutex);
+ lck_mtx_lock(&nfsrv_fmod_mutex);
/*
* Compute the time in the future when the
LIST_REMOVE(fp, fm_link);
LIST_INSERT_HEAD(head, fp, fm_link);
}
- lck_mtx_unlock(nfsrv_fmod_mutex);
+ lck_mtx_unlock(&nfsrv_fmod_mutex);
return;
}
}
nfsrv_fmod_pendtime);
}
done:
- lck_mtx_unlock(nfsrv_fmod_mutex);
+ lck_mtx_unlock(&nfsrv_fmod_mutex);
return;
}
#endif /* CONFIG_FSE */
mbuf_t m;
vnode_t vp;
struct nfs_filehandle nfh;
- struct nfs_export *nx;
+ struct nfs_export *nx = NULL;
struct nfs_export_options *nxo;
uio_t auio = NULL;
char *uio_bufp = NULL;
}
nfsmerr_if(error);
for (m = nmreq->nmc_mcur; m; m = mbuf_next(m)) {
- if ((mlen = mbuf_len(m)) > 0) {
+ if ((mlen = (int)mbuf_len(m)) > 0) {
uio_addiov(auio, CAST_USER_ADDR_T((caddr_t)mbuf_data(m)), mlen);
}
}
struct nfsrv_wg_delayhash *wpp;
uid_t saved_uid;
struct vnode_attr preattr, postattr;
- int error, mlen, i, ioflags, tlen;
+ int error, mlen, i, ioflags;
+ size_t tlen;
int preattrerr, postattrerr;
vnode_t vp;
mbuf_t m;
uio_t auio = NULL;
char *uio_bufp = NULL;
- u_quad_t cur_usec;
+ time_t cur_usec;
struct timeval now;
struct nfsm_chain *nmreq, nmrep;
nd->nd_mrep = NULL;
nd->nd_stable = NFS_WRITE_FILESYNC;
microuptime(&now);
- cur_usec = (u_quad_t)now.tv_sec * 1000000 + (u_quad_t)now.tv_usec;
+ cur_usec = now.tv_sec * 1000000 + now.tv_usec;
nd->nd_time = cur_usec +
((nd->nd_vers == NFS_VER3) ? nfsrv_wg_delay_v3 : nfsrv_wg_delay);
*/
loop1:
microuptime(&now);
- cur_usec = (u_quad_t)now.tv_sec * 1000000 + (u_quad_t)now.tv_usec;
+ cur_usec = now.tv_sec * 1000000 + now.tv_usec;
for (nd = slp->ns_tq.lh_first; nd; nd = owp) {
owp = nd->nd_tq.le_next;
if (nd->nd_time > cur_usec) {
*
* Add/Remove the socket in the nfsrv_sockwg queue as needed.
*/
- lck_mtx_lock(nfsd_mutex);
+ lck_mtx_lock(&nfsd_mutex);
if (slp->ns_wgtime) {
if (slp->ns_wgq.tqe_next == SLPNOLIST) {
TAILQ_INSERT_HEAD(&nfsrv_sockwg, slp, ns_wgq);
TAILQ_REMOVE(&nfsrv_sockwg, slp, ns_wgq);
slp->ns_wgq.tqe_next = SLPNOLIST;
}
- lck_mtx_unlock(nfsd_mutex);
+ lck_mtx_unlock(&nfsd_mutex);
return 0;
}
int
nfsrv_wg_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nd)
{
- int overlap, error;
+ int error;
+ off_t overlap;
mbuf_t mp, mpnext;
struct nfsrv_descript *p;
return EIO;
}
if (overlap > 0) {
- mbuf_adj(nd->nd_nmreq.nmc_mhead, overlap);
+ mbuf_adj(nd->nd_nmreq.nmc_mhead, (int)overlap);
}
mp = owp->nd_nmreq.nmc_mhead;
while ((mpnext = mbuf_next(mp))) {
nfsrv_wg_timer(__unused void *param0, __unused void *param1)
{
struct timeval now;
- uint64_t cur_usec, next_usec;
- int interval;
+ time_t cur_usec, next_usec;
+ time_t interval;
struct nfsrv_sock *slp;
int writes_pending = 0;
microuptime(&now);
- cur_usec = (uint64_t)now.tv_sec * 1000000 + (uint64_t)now.tv_usec;
+ cur_usec = now.tv_sec * 1000000 + now.tv_usec;
next_usec = cur_usec + (NFSRV_WGATHERDELAY * 1000);
- lck_mtx_lock(nfsd_mutex);
+ lck_mtx_lock(&nfsd_mutex);
TAILQ_FOREACH(slp, &nfsrv_sockwg, ns_wgq) {
if (slp->ns_wgtime) {
writes_pending++;
if (writes_pending == 0) {
nfsrv_wg_timer_on = 0;
- lck_mtx_unlock(nfsd_mutex);
+ lck_mtx_unlock(&nfsd_mutex);
return;
}
- lck_mtx_unlock(nfsd_mutex);
+ lck_mtx_unlock(&nfsd_mutex);
/*
* Return the number of msec to wait again
struct vnode_attr dpreattr, dpostattr, postattr;
struct vnode_attr va, *vap = &va;
struct nameidata ni;
- int error, rdev, dpreattrerr, dpostattrerr, postattrerr;
+ int error, dpreattrerr, dpostattrerr, postattrerr;
int how, exclusive_flag;
uint32_t len = 0, cnflags;
+ uint64_t rdev;
vnode_t vp, dvp, dirp;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
u_quad_t tempsize;
u_char cverf[NFSX_V3CREATEVERF];
uid_t saved_uid;
error = EEXIST;
break;
}
+ OS_FALLTHROUGH;
case NFS_CREATE_UNCHECKED:
error = nfsm_chain_get_sattr(nd, nmreq, vap);
break;
}
} else if (vap->va_type == VCHR || vap->va_type == VBLK ||
vap->va_type == VFIFO) {
- if (vap->va_type == VCHR && rdev == (int)0xffffffff) {
+ if (vap->va_type == VCHR && rdev == 0xffffffff) {
VATTR_SET(vap, va_type, VFIFO);
}
if (vap->va_type != VFIFO) {
vnode_t vp, dvp, dirp;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
uid_t saved_uid;
kauth_acl_t xacl = NULL;
struct nfsm_chain *nmreq, nmrep;
struct vnode_attr dpreattr, dpostattr;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
struct nfsm_chain *nmreq, nmrep;
error = 0;
if (!error) {
#if CONFIG_FSE
char *path = NULL;
- int plen;
+ int plen = 0;
fse_info finfo;
if (nfsrv_fsevents_enabled && need_fsevent(FSE_DELETE, dvp)) {
mount_ref(locked_mp, 0);
/* make a copy of to path to pass to nfsrv_namei() again */
- MALLOC_ZONE(topath, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
- if (topath) {
- bcopy(toni.ni_cnd.cn_pnbuf, topath, tolen + 1);
- }
+ topath = zalloc(ZV_NAMEI);
+ bcopy(toni.ni_cnd.cn_pnbuf, topath, tolen + 1);
/*
* nameidone has to happen before we vnode_put(tdvp)
vnode_put(tdvp);
/* make a copy of from path to pass to nfsrv_namei() again */
- MALLOC_ZONE(frompath, caddr_t, MAXPATHLEN, M_NAMEI, M_WAITOK);
- if (frompath) {
- bcopy(fromni.ni_cnd.cn_pnbuf, frompath, fromlen + 1);
- }
+ frompath = zalloc(ZV_NAMEI);
+ bcopy(fromni.ni_cnd.cn_pnbuf, frompath, fromlen + 1);
/*
* nameidone has to happen before we vnode_put(fdvp)
vnode_put(tdirp);
}
if (frompath) {
- FREE_ZONE(frompath, MAXPATHLEN, M_NAMEI);
+ NFS_ZFREE(ZV_NAMEI, frompath);
}
if (topath) {
- FREE_ZONE(topath, MAXPATHLEN, M_NAMEI);
+ NFS_ZFREE(ZV_NAMEI, topath);
}
if (saved_cred) {
kauth_cred_unref(&saved_cred);
vnode_t vp, dvp, dirp;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
uio_t auio = NULL;
char uio_buf[UIO_SIZEOF(1)];
struct nfsm_chain *nmreq, nmrep;
vnode_t vp, dvp, dirp;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
uid_t saved_uid;
kauth_acl_t xacl = NULL;
struct nfsm_chain *nmreq, nmrep;
struct vnode_attr dpreattr, dpostattr;
struct nfs_filehandle nfh;
struct nfs_export *nx = NULL;
- struct nfs_export_options *nxo;
+ struct nfs_export_options *nxo = NULL;
struct nameidata ni;
struct nfsm_chain *nmreq, nmrep;
if (!error) {
#if CONFIG_FSE
char *path = NULL;
- int plen;
+ int plen = 0;
fse_info finfo;
if (nfsrv_fsevents_enabled && need_fsevent(FSE_DELETE, dvp)) {
char uio_buf[UIO_SIZEOF(1)];
int len, nlen, rem, xfer, error, attrerr;
int siz, count, fullsiz, eofflag, nentries;
- u_quad_t off, toff, verf;
+ u_quad_t off, toff, verf = 0;
int vnopflag;
struct nfsm_chain *nmreq, nmrep;
{
vnode_t vp;
struct nfs_filehandle nfh;
- struct nfs_export *nx;
+ struct nfs_export *nx = NULL;
struct nfs_export_options *nxo;
int error, preattrerr, postattrerr, count;
struct vnode_attr preattr, postattr;
VFSATTR_INIT(&va);
VFSATTR_WANTED(&va, f_blocks);
+ VFSATTR_WANTED(&va, f_bfree);
VFSATTR_WANTED(&va, f_bavail);
VFSATTR_WANTED(&va, f_files);
VFSATTR_WANTED(&va, f_ffree);
maxsize = NFS_MAXDGRAMDATA;
prefsize = NFS_PREFDGRAMDATA;
} else {
- maxsize = prefsize = NFSRV_MAXDATA;
+ maxsize = prefsize = slp->ns_sobufsize ? slp->ns_sobufsize / 2 : NFSRV_MAXDATA;
}
nfsm_chain_add_32(error, &nmrep, maxsize);
vfs_context_t ctx,
mbuf_t *mrepp)
{
- int error, attrerr, linkmax, namemax;
- int chownres, notrunc, case_sensitive, case_preserving;
+ int error, attrerr, linkmax = 0, namemax = 0;
+ int chownres = 0, notrunc = 0, case_sensitive = 0, case_preserving = 0;
vnode_t vp;
struct vnode_attr attr;
struct nfs_filehandle nfh;
return error;
}
-#endif /* NFSSERVER */
+#endif /* CONFIG_NFS_SERVER */