nfs_commonport.c revision 240289
1136644Sache/*- 2136644Sache * Copyright (c) 1989, 1993 3136644Sache * The Regents of the University of California. All rights reserved. 4136644Sache * 5136644Sache * This code is derived from software contributed to Berkeley by 6136644Sache * Rick Macklem at The University of Guelph. 7136644Sache * 8136644Sache * Redistribution and use in source and binary forms, with or without 9136644Sache * modification, are permitted provided that the following conditions 10136644Sache * are met: 11136644Sache * 1. Redistributions of source code must retain the above copyright 12136644Sache * notice, this list of conditions and the following disclaimer. 13136644Sache * 2. Redistributions in binary form must reproduce the above copyright 14136644Sache * notice, this list of conditions and the following disclaimer in the 15136644Sache * documentation and/or other materials provided with the distribution. 16136644Sache * 4. Neither the name of the University nor the names of its contributors 17136644Sache * may be used to endorse or promote products derived from this software 18136644Sache * without specific prior written permission. 19136644Sache * 20136644Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21136644Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22136644Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23136644Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24136644Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25136644Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26136644Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27136644Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28136644Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29136644Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30136644Sache * SUCH DAMAGE. 31136644Sache * 32136644Sache */ 33136644Sache 34136644Sache#include <sys/cdefs.h> 35136644Sache__FBSDID("$FreeBSD: head/sys/fs/nfs/nfs_commonport.c 240289 2012-09-09 21:00:45Z rmacklem $"); 36136644Sache 37136644Sache/* 38136644Sache * Functions that need to be different for different versions of BSD 39136644Sache * kernel should be kept here, along with any global storage specific 40136644Sache * to this BSD variant. 41136644Sache */ 42136644Sache#include <fs/nfs/nfsport.h> 43136644Sache#include <sys/sysctl.h> 44136644Sache#include <vm/vm.h> 45136644Sache#include <vm/vm_object.h> 46136644Sache#include <vm/vm_page.h> 47136644Sache#include <vm/vm_param.h> 48136644Sache#include <vm/vm_map.h> 49136644Sache#include <vm/vm_kern.h> 50136644Sache#include <vm/vm_extern.h> 51136644Sache#include <vm/uma.h> 52136644Sache 53136644Sacheextern int nfscl_ticks; 54136644Sacheextern int nfsrv_nfsuserd; 55136644Sacheextern struct nfssockreq nfsrv_nfsuserdsock; 56136644Sacheextern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, 57136644Sache struct thread *); 58136644Sacheextern int nfsrv_useacl; 59136644Sachestruct mount nfsv4root_mnt; 60136644Sacheint newnfs_numnfsd = 0; 61136644Sachestruct nfsstats newnfsstats; 62136644Sacheint nfs_numnfscbd = 0; 63136644Sacheint nfscl_debuglevel = 0; 64136644Sachechar nfsv4_callbackaddr[INET6_ADDRSTRLEN]; 65136644Sachestruct callout newnfsd_callout; 66136644Sachevoid (*nfsd_call_servertimer)(void) = NULL; 67136644Sachevoid (*ncl_call_invalcaches)(struct vnode *) = NULL; 68136644Sache 69136644Sachestatic int nfs_realign_test; 70136644Sachestatic int nfs_realign_count; 71136644Sache 72136644SacheSYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "New NFS filesystem"); 73136644SacheSYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 74136644Sache 0, "Number of realign tests done"); 75136644SacheSYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 76136644Sache 0, "Number of mbuf realignments done"); 77136644SacheSYSCTL_STRING(_vfs_nfs, OID_AUTO, callback_addr, CTLFLAG_RW, 78136644Sache nfsv4_callbackaddr, sizeof(nfsv4_callbackaddr), 79136644Sache "NFSv4 callback addr for server to use"); 80136644SacheSYSCTL_INT(_vfs_nfs, OID_AUTO, debuglevel, CTLFLAG_RW, &nfscl_debuglevel, 81136644Sache 0, "Debug level for new nfs client"); 82136644Sache 83136644Sache/* 84136644Sache * Defines for malloc 85136644Sache * (Here for FreeBSD, since they allocate storage.) 86136644Sache */ 87136644SacheMALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache"); 88136644SacheMALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id"); 89136644SacheMALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", 90136644Sache "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); 91136644SacheMALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock"); 92136644SacheMALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file"); 93136644SacheMALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string"); 94136644SacheMALLOC_DEFINE(M_NEWNFSUSERGROUP, "NFSD usrgroup", "NFSD V4 User/group map"); 95136644SacheMALLOC_DEFINE(M_NEWNFSDREQ, "NFS req", "NFS request header"); 96136644SacheMALLOC_DEFINE(M_NEWNFSFH, "NFS fh", "NFS file handle"); 97136644SacheMALLOC_DEFINE(M_NEWNFSCLOWNER, "NFSCL owner", "NFSCL Open Owner"); 98136644SacheMALLOC_DEFINE(M_NEWNFSCLOPEN, "NFSCL open", "NFSCL Open"); 99136644SacheMALLOC_DEFINE(M_NEWNFSCLDELEG, "NFSCL deleg", "NFSCL Delegation"); 100136644SacheMALLOC_DEFINE(M_NEWNFSCLCLIENT, "NFSCL client", "NFSCL Client"); 101136644SacheMALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner"); 102136644SacheMALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock"); 103136644SacheMALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "New nfs vnode"); 104136644SacheMALLOC_DEFINE(M_NEWNFSDIRECTIO, "NEWdirectio", "New nfs Direct IO buffer"); 105136644SacheMALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroffdiroff", 106136644Sache "New NFS directory offset data"); 107136644SacheMALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", 108136644Sache "New NFS local lock rollback"); 109136644Sache 110136644Sache/* 111136644Sache * Definition of mutex locks. 112136644Sache * newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list 113136644Sache * and assorted other nfsd structures. 114136644Sache */ 115136644Sachestruct mtx newnfsd_mtx; 116136644Sachestruct mtx nfs_sockl_mutex; 117136644Sachestruct mtx nfs_state_mutex; 118136644Sachestruct mtx nfs_nameid_mutex; 119136644Sachestruct mtx nfs_req_mutex; 120136644Sachestruct mtx nfs_slock_mutex; 121136644Sache 122136644Sache/* local functions */ 123136644Sachestatic int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); 124136644Sache 125136644Sache#ifdef __NO_STRICT_ALIGNMENT 126136644Sache/* 127136644Sache * These architectures don't need re-alignment, so just return. 128136644Sache */ 129136644Sachevoid 130136644Sachenewnfs_realign(struct mbuf **pm) 131136644Sache{ 132136644Sache 133136644Sache return; 134136644Sache} 135136644Sache#else /* !__NO_STRICT_ALIGNMENT */ 136136644Sache/* 137136644Sache * newnfs_realign: 138136644Sache * 139136644Sache * Check for badly aligned mbuf data and realign by copying the unaligned 140136644Sache * portion of the data into a new mbuf chain and freeing the portions 141136644Sache * of the old chain that were replaced. 142136644Sache * 143136644Sache * We cannot simply realign the data within the existing mbuf chain 144136644Sache * because the underlying buffers may contain other rpc commands and 145136644Sache * we cannot afford to overwrite them. 146136644Sache * 147136644Sache * We would prefer to avoid this situation entirely. The situation does 148136644Sache * not occur with NFS/UDP and is supposed to only occassionally occur 149136644Sache * with TCP. Use vfs.nfs.realign_count and realign_test to check this. 150136644Sache * 151136644Sache */ 152136644Sachevoid 153136644Sachenewnfs_realign(struct mbuf **pm) 154136644Sache{ 155136644Sache struct mbuf *m, *n; 156136644Sache int off, space; 157136644Sache 158136644Sache ++nfs_realign_test; 159136644Sache while ((m = *pm) != NULL) { 160136644Sache if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { 161136644Sache /* 162136644Sache * NB: we can't depend on m_pkthdr.len to help us 163136644Sache * decide what to do here. May not be worth doing 164136644Sache * the m_length calculation as m_copyback will 165136644Sache * expand the mbuf chain below as needed. 166136644Sache */ 167136644Sache space = m_length(m, NULL); 168136644Sache if (space >= MINCLSIZE) { 169136644Sache /* NB: m_copyback handles space > MCLBYTES */ 170136644Sache n = m_getcl(M_WAITOK, MT_DATA, 0); 171136644Sache } else 172136644Sache n = m_get(M_WAITOK, MT_DATA); 173136644Sache if (n == NULL) 174136644Sache return; 175136644Sache /* 176136644Sache * Align the remainder of the mbuf chain. 177136644Sache */ 178136644Sache n->m_len = 0; 179136644Sache off = 0; 180136644Sache while (m != NULL) { 181136644Sache m_copyback(n, off, m->m_len, mtod(m, caddr_t)); 182136644Sache off += m->m_len; 183136644Sache m = m->m_next; 184136644Sache } 185136644Sache m_freem(*pm); 186136644Sache *pm = n; 187136644Sache ++nfs_realign_count; 188136644Sache break; 189136644Sache } 190136644Sache pm = &m->m_next; 191136644Sache } 192136644Sache} 193136644Sache#endif /* __NO_STRICT_ALIGNMENT */ 194136644Sache 195136644Sache#ifdef notdef 196136644Sachestatic void 197136644Sachenfsrv_object_create(struct vnode *vp, struct thread *td) 198136644Sache{ 199136644Sache 200136644Sache if (vp == NULL || vp->v_type != VREG) 201136644Sache return; 202136644Sache (void) vfs_object_create(vp, td, td->td_ucred); 203136644Sache} 204136644Sache#endif 205136644Sache 206136644Sache/* 207136644Sache * Look up a file name. Basically just initialize stuff and call namei(). 208136644Sache */ 209136644Sacheint 210136644Sachenfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p) 211136644Sache{ 212136644Sache int error; 213136644Sache 214136644Sache NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE, fname, 215136644Sache p); 216136644Sache error = namei(ndp); 217136644Sache if (!error) { 218136644Sache NDFREE(ndp, NDF_ONLY_PNBUF); 219136644Sache } 220136644Sache return (error); 221136644Sache} 222136644Sache 223136644Sache/* 224136644Sache * Copy NFS uid, gids to the cred structure. 225136644Sache */ 226136644Sachevoid 227136644Sachenewnfs_copycred(struct nfscred *nfscr, struct ucred *cr) 228136644Sache{ 229136644Sache 230136644Sache KASSERT(nfscr->nfsc_ngroups >= 0, 231136644Sache ("newnfs_copycred: negative nfsc_ngroups")); 232136644Sache cr->cr_uid = nfscr->nfsc_uid; 233136644Sache crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); 234136644Sache} 235136644Sache 236136644Sache/* 237136644Sache * Map args from nfsmsleep() to msleep(). 238136644Sache */ 239136644Sacheint 240136644Sachenfsmsleep(void *chan, void *mutex, int prio, const char *wmesg, 241136644Sache struct timespec *ts) 242136644Sache{ 243136644Sache u_int64_t nsecval; 244136644Sache int error, timeo; 245136644Sache 246136644Sache if (ts) { 247136644Sache timeo = hz * ts->tv_sec; 248136644Sache nsecval = (u_int64_t)ts->tv_nsec; 249136644Sache nsecval = ((nsecval * ((u_int64_t)hz)) + 500000000) / 250136644Sache 1000000000; 251136644Sache timeo += (int)nsecval; 252136644Sache } else { 253136644Sache timeo = 0; 254136644Sache } 255136644Sache error = msleep(chan, (struct mtx *)mutex, prio, wmesg, timeo); 256136644Sache return (error); 257136644Sache} 258136644Sache 259136644Sache/* 260136644Sache * Get the file system info for the server. For now, just assume FFS. 261136644Sache */ 262136644Sachevoid 263136644Sachenfsvno_getfs(struct nfsfsinfo *sip, int isdgram) 264136644Sache{ 265136644Sache int pref; 266136644Sache 267136644Sache /* 268136644Sache * XXX 269136644Sache * There should be file system VFS OP(s) to get this information. 270136644Sache * For now, assume ufs. 271136644Sache */ 272136644Sache if (isdgram) 273136644Sache pref = NFS_MAXDGRAMDATA; 274136644Sache else 275136644Sache pref = NFS_MAXDATA; 276136644Sache sip->fs_rtmax = NFS_MAXDATA; 277136644Sache sip->fs_rtpref = pref; 278136644Sache sip->fs_rtmult = NFS_FABLKSIZE; 279136644Sache sip->fs_wtmax = NFS_MAXDATA; 280136644Sache sip->fs_wtpref = pref; 281136644Sache sip->fs_wtmult = NFS_FABLKSIZE; 282136644Sache sip->fs_dtpref = pref; 283136644Sache sip->fs_maxfilesize = 0xffffffffffffffffull; 284136644Sache sip->fs_timedelta.tv_sec = 0; 285136644Sache sip->fs_timedelta.tv_nsec = 1; 286136644Sache sip->fs_properties = (NFSV3FSINFO_LINK | 287136644Sache NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 288136644Sache NFSV3FSINFO_CANSETTIME); 289136644Sache} 290136644Sache 291136644Sache/* 292136644Sache * Do the pathconf vnode op. 293136644Sache */ 294136644Sacheint 295136644Sachenfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, 296136644Sache struct ucred *cred, struct thread *p) 297136644Sache{ 298136644Sache int error; 299136644Sache 300136644Sache error = VOP_PATHCONF(vp, flag, retf); 301136644Sache if (error == EOPNOTSUPP || error == EINVAL) { 302136644Sache /* 303136644Sache * Some file systems return EINVAL for name arguments not 304136644Sache * supported and some return EOPNOTSUPP for this case. 305136644Sache * So the NFSv3 Pathconf RPC doesn't fail for these cases, 306136644Sache * just fake them. 307136644Sache */ 308136644Sache switch (flag) { 309136644Sache case _PC_LINK_MAX: 310136644Sache *retf = LINK_MAX; 311136644Sache break; 312136644Sache case _PC_NAME_MAX: 313136644Sache *retf = NAME_MAX; 314136644Sache break; 315136644Sache case _PC_CHOWN_RESTRICTED: 316136644Sache *retf = 1; 317136644Sache break; 318136644Sache case _PC_NO_TRUNC: 319136644Sache *retf = 1; 320136644Sache break; 321136644Sache default: 322136644Sache /* 323136644Sache * Only happens if a _PC_xxx is added to the server, 324136644Sache * but this isn't updated. 325136644Sache */ 326136644Sache *retf = 0; 327136644Sache printf("nfsrvd pathconf flag=%d not supp\n", flag); 328136644Sache }; 329136644Sache error = 0; 330136644Sache } 331136644Sache NFSEXITCODE(error); 332136644Sache return (error); 333136644Sache} 334136644Sache 335136644Sache/* Fake nfsrv_atroot. Just return 0 */ 336136644Sacheint 337136644Sachenfsrv_atroot(struct vnode *vp, long *retp) 338136644Sache{ 339136644Sache 340136644Sache return (0); 341136644Sache} 342136644Sache 343136644Sache/* 344136644Sache * Set the credentials to refer to root. 345136644Sache * If only the various BSDen could agree on whether cr_gid is a separate 346136644Sache * field or cr_groups[0]... 347136644Sache */ 348136644Sachevoid 349136644Sachenewnfs_setroot(struct ucred *cred) 350136644Sache{ 351136644Sache 352136644Sache cred->cr_uid = 0; 353136644Sache cred->cr_groups[0] = 0; 354136644Sache cred->cr_ngroups = 1; 355136644Sache} 356136644Sache 357136644Sache/* 358136644Sache * Get the client credential. Used for Renew and recovery. 359136644Sache */ 360136644Sachestruct ucred * 361136644Sachenewnfs_getcred(void) 362136644Sache{ 363136644Sache struct ucred *cred; 364136644Sache struct thread *td = curthread; 365136644Sache 366136644Sache cred = crdup(td->td_ucred); 367136644Sache newnfs_setroot(cred); 368136644Sache return (cred); 369136644Sache} 370136644Sache 371136644Sache/* 372136644Sache * Nfs timer routine 373136644Sache * Call the nfsd's timer function once/sec. 374136644Sache */ 375136644Sachevoid 376136644Sachenewnfs_timer(void *arg) 377136644Sache{ 378136644Sache static time_t lasttime = 0; 379136644Sache /* 380136644Sache * Call the server timer, if set up. 381136644Sache * The argument indicates if it is the next second and therefore 382136644Sache * leases should be checked. 383136644Sache */ 384136644Sache if (lasttime != NFSD_MONOSEC) { 385136644Sache lasttime = NFSD_MONOSEC; 386136644Sache if (nfsd_call_servertimer != NULL) 387136644Sache (*nfsd_call_servertimer)(); 388136644Sache } 389136644Sache callout_reset(&newnfsd_callout, nfscl_ticks, newnfs_timer, NULL); 390136644Sache} 391136644Sache 392136644Sache 393136644Sache/* 394136644Sache * Sleep for a short period of time unless errval == NFSERR_GRACE, where 395136644Sache * the sleep should be for 5 seconds. 396136644Sache * Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on 397136644Sache * an event that never gets a wakeup. Only return EINTR or 0. 398136644Sache */ 399136644Sacheint 400136644Sachenfs_catnap(int prio, int errval, const char *wmesg) 401136644Sache{ 402136644Sache static int non_event; 403136644Sache int ret; 404136644Sache 405136644Sache if (errval == NFSERR_GRACE) 406136644Sache ret = tsleep(&non_event, prio, wmesg, 5 * hz); 407136644Sache else 408136644Sache ret = tsleep(&non_event, prio, wmesg, 1); 409136644Sache if (ret != EINTR) 410136644Sache ret = 0; 411136644Sache return (ret); 412136644Sache} 413136644Sache 414136644Sache/* 415136644Sache * Get referral. For now, just fail. 416136644Sache */ 417136644Sachestruct nfsreferral * 418136644Sachenfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno) 419136644Sache{ 420136644Sache 421136644Sache return (NULL); 422136644Sache} 423136644Sache 424136644Sachestatic int 425136644Sachenfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap) 426136644Sache{ 427136644Sache int error; 428136644Sache 429136644Sache error = nfssvc_call(td, uap, td->td_ucred); 430136644Sache NFSEXITCODE(error); 431136644Sache return (error); 432136644Sache} 433136644Sache 434136644Sachestatic int 435136644Sachenfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 436136644Sache{ 437136644Sache int error = EINVAL; 438136644Sache struct nfsd_idargs nid; 439136644Sache 440136644Sache if (uap->flag & NFSSVC_IDNAME) { 441136644Sache error = copyin(uap->argp, (caddr_t)&nid, sizeof (nid)); 442136644Sache if (error) 443136644Sache goto out; 444136644Sache error = nfssvc_idname(&nid); 445136644Sache goto out; 446136644Sache } else if (uap->flag & NFSSVC_GETSTATS) { 447136644Sache error = copyout(&newnfsstats, 448136644Sache CAST_USER_ADDR_T(uap->argp), sizeof (newnfsstats)); 449136644Sache if (error == 0) { 450136644Sache if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) { 451136644Sache newnfsstats.attrcache_hits = 0; 452136644Sache newnfsstats.attrcache_misses = 0; 453136644Sache newnfsstats.lookupcache_hits = 0; 454136644Sache newnfsstats.lookupcache_misses = 0; 455136644Sache newnfsstats.direofcache_hits = 0; 456136644Sache newnfsstats.direofcache_misses = 0; 457136644Sache newnfsstats.accesscache_hits = 0; 458136644Sache newnfsstats.accesscache_misses = 0; 459136644Sache newnfsstats.biocache_reads = 0; 460136644Sache newnfsstats.read_bios = 0; 461136644Sache newnfsstats.read_physios = 0; 462136644Sache newnfsstats.biocache_writes = 0; 463136644Sache newnfsstats.write_bios = 0; 464136644Sache newnfsstats.write_physios = 0; 465136644Sache newnfsstats.biocache_readlinks = 0; 466136644Sache newnfsstats.readlink_bios = 0; 467136644Sache newnfsstats.biocache_readdirs = 0; 468136644Sache newnfsstats.readdir_bios = 0; 469136644Sache newnfsstats.rpcretries = 0; 470136644Sache newnfsstats.rpcrequests = 0; 471136644Sache newnfsstats.rpctimeouts = 0; 472136644Sache newnfsstats.rpcunexpected = 0; 473136644Sache newnfsstats.rpcinvalid = 0; 474136644Sache bzero(newnfsstats.rpccnt, 475136644Sache sizeof(newnfsstats.rpccnt)); 476136644Sache } 477136644Sache if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) { 478136644Sache newnfsstats.srvrpc_errs = 0; 479136644Sache newnfsstats.srv_errs = 0; 480136644Sache newnfsstats.srvcache_inproghits = 0; 481136644Sache newnfsstats.srvcache_idemdonehits = 0; 482136644Sache newnfsstats.srvcache_nonidemdonehits = 0; 483136644Sache newnfsstats.srvcache_misses = 0; 484136644Sache newnfsstats.srvcache_tcppeak = 0; 485136644Sache newnfsstats.srvclients = 0; 486136644Sache newnfsstats.srvopenowners = 0; 487136644Sache newnfsstats.srvopens = 0; 488136644Sache newnfsstats.srvlockowners = 0; 489136644Sache newnfsstats.srvlocks = 0; 490136644Sache newnfsstats.srvdelegates = 0; 491136644Sache newnfsstats.clopenowners = 0; 492136644Sache newnfsstats.clopens = 0; 493136644Sache newnfsstats.cllockowners = 0; 494136644Sache newnfsstats.cllocks = 0; 495136644Sache newnfsstats.cldelegates = 0; 496136644Sache newnfsstats.cllocalopenowners = 0; 497136644Sache newnfsstats.cllocalopens = 0; 498136644Sache newnfsstats.cllocallockowners = 0; 499136644Sache newnfsstats.cllocallocks = 0; 500136644Sache bzero(newnfsstats.srvrpccnt, 501136644Sache sizeof(newnfsstats.srvrpccnt)); 502136644Sache bzero(newnfsstats.cbrpccnt, 503136644Sache sizeof(newnfsstats.cbrpccnt)); 504136644Sache } 505136644Sache } 506136644Sache goto out; 507136644Sache } else if (uap->flag & NFSSVC_NFSUSERDPORT) { 508136644Sache u_short sockport; 509136644Sache 510136644Sache error = copyin(uap->argp, (caddr_t)&sockport, 511136644Sache sizeof (u_short)); 512136644Sache if (!error) 513136644Sache error = nfsrv_nfsuserdport(sockport, p); 514136644Sache } else if (uap->flag & NFSSVC_NFSUSERDDELPORT) { 515136644Sache nfsrv_nfsuserddelport(); 516136644Sache error = 0; 517136644Sache } 518136644Sache 519136644Sacheout: 520136644Sache NFSEXITCODE(error); 521136644Sache return (error); 522136644Sache} 523136644Sache 524136644Sache/* 525136644Sache * called by all three modevent routines, so that it gets things 526136644Sache * initialized soon enough. 527136644Sache */ 528136644Sachevoid 529136644Sachenewnfs_portinit(void) 530136644Sache{ 531136644Sache static int inited = 0; 532136644Sache 533136644Sache if (inited) 534136644Sache return; 535136644Sache inited = 1; 536136644Sache /* Initialize SMP locks used by both client and server. */ 537136644Sache mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF); 538136644Sache mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF); 539136644Sache} 540136644Sache 541136644Sache/* 542136644Sache * Determine if the file system supports NFSv4 ACLs. 543136644Sache * Return 1 if it does, 0 otherwise. 544136644Sache */ 545136644Sacheint 546136644Sachenfs_supportsnfsv4acls(struct vnode *vp) 547136644Sache{ 548136644Sache int error; 549 register_t retval; 550 551 ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls"); 552 553 if (nfsrv_useacl == 0) 554 return (0); 555 error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval); 556 if (error == 0 && retval != 0) 557 return (1); 558 return (0); 559} 560 561extern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *); 562 563/* 564 * Called once to initialize data structures... 565 */ 566static int 567nfscommon_modevent(module_t mod, int type, void *data) 568{ 569 int error = 0; 570 static int loaded = 0; 571 572 switch (type) { 573 case MOD_LOAD: 574 if (loaded) 575 goto out; 576 newnfs_portinit(); 577 mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF); 578 mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF); 579 mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF); 580 mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF); 581 mtx_init(&nfsrv_nfsuserdsock.nr_mtx, "nfsuserd", NULL, 582 MTX_DEF); 583 callout_init(&newnfsd_callout, CALLOUT_MPSAFE); 584 newnfs_init(); 585 nfsd_call_nfscommon = nfssvc_nfscommon; 586 loaded = 1; 587 break; 588 589 case MOD_UNLOAD: 590 if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != 0 || 591 nfs_numnfscbd != 0) { 592 error = EBUSY; 593 break; 594 } 595 596 nfsd_call_nfscommon = NULL; 597 callout_drain(&newnfsd_callout); 598 /* and get rid of the mutexes */ 599 mtx_destroy(&nfs_nameid_mutex); 600 mtx_destroy(&newnfsd_mtx); 601 mtx_destroy(&nfs_state_mutex); 602 mtx_destroy(&nfs_sockl_mutex); 603 mtx_destroy(&nfs_slock_mutex); 604 mtx_destroy(&nfs_req_mutex); 605 mtx_destroy(&nfsrv_nfsuserdsock.nr_mtx); 606 loaded = 0; 607 break; 608 default: 609 error = EOPNOTSUPP; 610 break; 611 } 612 613out: 614 NFSEXITCODE(error); 615 return error; 616} 617static moduledata_t nfscommon_mod = { 618 "nfscommon", 619 nfscommon_modevent, 620 NULL, 621}; 622DECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY); 623 624/* So that loader and kldload(2) can find us, wherever we are.. */ 625MODULE_VERSION(nfscommon, 1); 626MODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1); 627MODULE_DEPEND(nfscommon, krpc, 1, 1, 1); 628 629