nfs_commonport.c revision 224078
1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1989, 1993 3191783Srmacklem * The Regents of the University of California. All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This code is derived from software contributed to Berkeley by 6191783Srmacklem * Rick Macklem at The University of Guelph. 7191783Srmacklem * 8191783Srmacklem * Redistribution and use in source and binary forms, with or without 9191783Srmacklem * modification, are permitted provided that the following conditions 10191783Srmacklem * are met: 11191783Srmacklem * 1. Redistributions of source code must retain the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer. 13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14191783Srmacklem * notice, this list of conditions and the following disclaimer in the 15191783Srmacklem * documentation and/or other materials provided with the distribution. 16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors 17191783Srmacklem * may be used to endorse or promote products derived from this software 18191783Srmacklem * without specific prior written permission. 19191783Srmacklem * 20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30191783Srmacklem * SUCH DAMAGE. 31191783Srmacklem * 32191783Srmacklem */ 33191783Srmacklem 34191783Srmacklem#include <sys/cdefs.h> 35191783Srmacklem__FBSDID("$FreeBSD: head/sys/fs/nfs/nfs_commonport.c 224078 2011-07-16 08:05:17Z zack $"); 36191783Srmacklem 37191783Srmacklem/* 38191783Srmacklem * Functions that need to be different for different versions of BSD 39191783Srmacklem * kernel should be kept here, along with any global storage specific 40191783Srmacklem * to this BSD variant. 41191783Srmacklem */ 42191783Srmacklem#include <fs/nfs/nfsport.h> 43191783Srmacklem#include <sys/sysctl.h> 44191783Srmacklem#include <vm/vm.h> 45191783Srmacklem#include <vm/vm_object.h> 46191783Srmacklem#include <vm/vm_page.h> 47191783Srmacklem#include <vm/vm_param.h> 48191783Srmacklem#include <vm/vm_map.h> 49191783Srmacklem#include <vm/vm_kern.h> 50191783Srmacklem#include <vm/vm_extern.h> 51191783Srmacklem#include <vm/uma.h> 52191783Srmacklem#include <vm/uma_int.h> 53191783Srmacklem 54191783Srmacklemextern int nfscl_ticks; 55191783Srmacklemextern int nfsrv_nfsuserd; 56191783Srmacklemextern struct nfssockreq nfsrv_nfsuserdsock; 57191783Srmacklemextern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, 58191783Srmacklem struct thread *); 59191783Srmacklemextern int nfsrv_useacl; 60191783Srmacklemstruct mount nfsv4root_mnt; 61191783Srmacklemint newnfs_numnfsd = 0; 62191783Srmacklemstruct nfsstats newnfsstats; 63191783Srmacklemint nfs_numnfscbd = 0; 64191783Srmacklemchar nfsv4_callbackaddr[INET6_ADDRSTRLEN]; 65191783Srmacklemstruct callout newnfsd_callout; 66191783Srmacklemvoid (*nfsd_call_servertimer)(void) = NULL; 67191783Srmacklemvoid (*ncl_call_invalcaches)(struct vnode *) = NULL; 68191783Srmacklem 69191783Srmacklemstatic int nfs_realign_test; 70191783Srmacklemstatic int nfs_realign_count; 71191783Srmacklem 72221973SrmacklemSYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW, 0, "New NFS filesystem"); 73221973SrmacklemSYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 74220751Srmacklem 0, "Number of realign tests done"); 75221973SrmacklemSYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 76220751Srmacklem 0, "Number of mbuf realignments done"); 77221973SrmacklemSYSCTL_STRING(_vfs_nfs, OID_AUTO, callback_addr, CTLFLAG_RW, 78220751Srmacklem nfsv4_callbackaddr, sizeof(nfsv4_callbackaddr), 79220751Srmacklem "NFSv4 callback addr for server to use"); 80191783Srmacklem 81191783Srmacklem/* 82191783Srmacklem * Defines for malloc 83191783Srmacklem * (Here for FreeBSD, since they allocate storage.) 84191783Srmacklem */ 85191783SrmacklemMALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache"); 86191783SrmacklemMALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id"); 87205941SrmacklemMALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", 88205941Srmacklem "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); 89191783SrmacklemMALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock"); 90191783SrmacklemMALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file"); 91191783SrmacklemMALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string"); 92191783SrmacklemMALLOC_DEFINE(M_NEWNFSUSERGROUP, "NFSD usrgroup", "NFSD V4 User/group map"); 93191783SrmacklemMALLOC_DEFINE(M_NEWNFSDREQ, "NFS req", "NFS request header"); 94191783SrmacklemMALLOC_DEFINE(M_NEWNFSFH, "NFS fh", "NFS file handle"); 95191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLOWNER, "NFSCL owner", "NFSCL Open Owner"); 96191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLOPEN, "NFSCL open", "NFSCL Open"); 97191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLDELEG, "NFSCL deleg", "NFSCL Delegation"); 98191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLCLIENT, "NFSCL client", "NFSCL Client"); 99191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner"); 100191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock"); 101191783SrmacklemMALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "New nfs vnode"); 102191783SrmacklemMALLOC_DEFINE(M_NEWNFSDIRECTIO, "NEWdirectio", "New nfs Direct IO buffer"); 103205941SrmacklemMALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroffdiroff", 104205941Srmacklem "New NFS directory offset data"); 105205941SrmacklemMALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", 106205941Srmacklem "New NFS local lock rollback"); 107191783Srmacklem 108191783Srmacklem/* 109191783Srmacklem * Definition of mutex locks. 110191783Srmacklem * newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list 111191783Srmacklem * and assorted other nfsd structures. 112191783Srmacklem * Giant is used to protect the nfsd list and count, which is just 113191783Srmacklem * updated when nfsd's start/stop and is grabbed for nfsrvd_dorpc() 114191783Srmacklem * for the VFS ops. 115191783Srmacklem */ 116191783Srmacklemstruct mtx newnfsd_mtx; 117191783Srmacklemstruct mtx nfs_sockl_mutex; 118191783Srmacklemstruct mtx nfs_state_mutex; 119191783Srmacklemstruct mtx nfs_nameid_mutex; 120191783Srmacklemstruct mtx nfs_req_mutex; 121191783Srmacklemstruct mtx nfs_slock_mutex; 122191783Srmacklem 123191783Srmacklem/* local functions */ 124191783Srmacklemstatic int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); 125191783Srmacklem 126205572Srmacklem#ifdef __NO_STRICT_ALIGNMENT 127191783Srmacklem/* 128191783Srmacklem * These architectures don't need re-alignment, so just return. 129191783Srmacklem */ 130191783Srmacklemvoid 131191783Srmacklemnewnfs_realign(struct mbuf **pm) 132191783Srmacklem{ 133191783Srmacklem 134191783Srmacklem return; 135191783Srmacklem} 136205572Srmacklem#else /* !__NO_STRICT_ALIGNMENT */ 137191783Srmacklem/* 138192695Srmacklem * newnfs_realign: 139191783Srmacklem * 140191783Srmacklem * Check for badly aligned mbuf data and realign by copying the unaligned 141191783Srmacklem * portion of the data into a new mbuf chain and freeing the portions 142191783Srmacklem * of the old chain that were replaced. 143191783Srmacklem * 144191783Srmacklem * We cannot simply realign the data within the existing mbuf chain 145191783Srmacklem * because the underlying buffers may contain other rpc commands and 146191783Srmacklem * we cannot afford to overwrite them. 147191783Srmacklem * 148191783Srmacklem * We would prefer to avoid this situation entirely. The situation does 149191783Srmacklem * not occur with NFS/UDP and is supposed to only occassionally occur 150191783Srmacklem * with TCP. Use vfs.nfs.realign_count and realign_test to check this. 151192695Srmacklem * 152191783Srmacklem */ 153191783Srmacklemvoid 154191783Srmacklemnewnfs_realign(struct mbuf **pm) 155191783Srmacklem{ 156192695Srmacklem struct mbuf *m, *n; 157192695Srmacklem int off, space; 158191783Srmacklem 159191783Srmacklem ++nfs_realign_test; 160191783Srmacklem while ((m = *pm) != NULL) { 161191783Srmacklem if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { 162192695Srmacklem /* 163192695Srmacklem * NB: we can't depend on m_pkthdr.len to help us 164192695Srmacklem * decide what to do here. May not be worth doing 165192695Srmacklem * the m_length calculation as m_copyback will 166192695Srmacklem * expand the mbuf chain below as needed. 167192695Srmacklem */ 168192695Srmacklem space = m_length(m, NULL); 169192695Srmacklem if (space >= MINCLSIZE) { 170192695Srmacklem /* NB: m_copyback handles space > MCLBYTES */ 171192695Srmacklem n = m_getcl(M_WAITOK, MT_DATA, 0); 172192695Srmacklem } else 173192695Srmacklem n = m_get(M_WAITOK, MT_DATA); 174192695Srmacklem if (n == NULL) 175192695Srmacklem return; 176192695Srmacklem /* 177192695Srmacklem * Align the remainder of the mbuf chain. 178192695Srmacklem */ 179192695Srmacklem n->m_len = 0; 180192695Srmacklem off = 0; 181192695Srmacklem while (m != NULL) { 182192695Srmacklem m_copyback(n, off, m->m_len, mtod(m, caddr_t)); 183192695Srmacklem off += m->m_len; 184192695Srmacklem m = m->m_next; 185191783Srmacklem } 186192695Srmacklem m_freem(*pm); 187192695Srmacklem *pm = n; 188192695Srmacklem ++nfs_realign_count; 189191783Srmacklem break; 190191783Srmacklem } 191191783Srmacklem pm = &m->m_next; 192191783Srmacklem } 193191783Srmacklem} 194205572Srmacklem#endif /* __NO_STRICT_ALIGNMENT */ 195191783Srmacklem 196191783Srmacklem#ifdef notdef 197191783Srmacklemstatic void 198191783Srmacklemnfsrv_object_create(struct vnode *vp, struct thread *td) 199191783Srmacklem{ 200191783Srmacklem 201191783Srmacklem if (vp == NULL || vp->v_type != VREG) 202191783Srmacklem return; 203191783Srmacklem (void) vfs_object_create(vp, td, td->td_ucred); 204191783Srmacklem} 205191783Srmacklem#endif 206191783Srmacklem 207191783Srmacklem/* 208191783Srmacklem * Look up a file name. Basically just initialize stuff and call namei(). 209191783Srmacklem */ 210191783Srmacklemint 211191783Srmacklemnfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p) 212191783Srmacklem{ 213191783Srmacklem int error; 214191783Srmacklem 215210268Srmacklem NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE, UIO_USERSPACE, fname, 216210268Srmacklem p); 217191783Srmacklem error = namei(ndp); 218191783Srmacklem if (!error) { 219191783Srmacklem NDFREE(ndp, NDF_ONLY_PNBUF); 220191783Srmacklem } 221191783Srmacklem return (error); 222191783Srmacklem} 223191783Srmacklem 224191783Srmacklem/* 225191783Srmacklem * Copy NFS uid, gids to the cred structure. 226191783Srmacklem */ 227191783Srmacklemvoid 228191783Srmacklemnewnfs_copycred(struct nfscred *nfscr, struct ucred *cr) 229191783Srmacklem{ 230191783Srmacklem 231206688Srmacklem KASSERT(nfscr->nfsc_ngroups >= 0, 232206688Srmacklem ("newnfs_copycred: negative nfsc_ngroups")); 233191783Srmacklem cr->cr_uid = nfscr->nfsc_uid; 234194498Sbrooks crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); 235191783Srmacklem} 236191783Srmacklem 237191783Srmacklem/* 238191783Srmacklem * Map args from nfsmsleep() to msleep(). 239191783Srmacklem */ 240191783Srmacklemint 241191783Srmacklemnfsmsleep(void *chan, void *mutex, int prio, const char *wmesg, 242191783Srmacklem struct timespec *ts) 243191783Srmacklem{ 244191783Srmacklem u_int64_t nsecval; 245191783Srmacklem int error, timeo; 246191783Srmacklem 247191783Srmacklem if (ts) { 248191783Srmacklem timeo = hz * ts->tv_sec; 249191783Srmacklem nsecval = (u_int64_t)ts->tv_nsec; 250191783Srmacklem nsecval = ((nsecval * ((u_int64_t)hz)) + 500000000) / 251191783Srmacklem 1000000000; 252191783Srmacklem timeo += (int)nsecval; 253191783Srmacklem } else { 254191783Srmacklem timeo = 0; 255191783Srmacklem } 256191783Srmacklem error = msleep(chan, (struct mtx *)mutex, prio, wmesg, timeo); 257191783Srmacklem return (error); 258191783Srmacklem} 259191783Srmacklem 260191783Srmacklem/* 261191783Srmacklem * Get the file system info for the server. For now, just assume FFS. 262191783Srmacklem */ 263191783Srmacklemvoid 264191783Srmacklemnfsvno_getfs(struct nfsfsinfo *sip, int isdgram) 265191783Srmacklem{ 266191783Srmacklem int pref; 267191783Srmacklem 268191783Srmacklem /* 269191783Srmacklem * XXX 270191783Srmacklem * There should be file system VFS OP(s) to get this information. 271191783Srmacklem * For now, assume ufs. 272191783Srmacklem */ 273191783Srmacklem if (isdgram) 274191783Srmacklem pref = NFS_MAXDGRAMDATA; 275191783Srmacklem else 276191783Srmacklem pref = NFS_MAXDATA; 277191783Srmacklem sip->fs_rtmax = NFS_MAXDATA; 278191783Srmacklem sip->fs_rtpref = pref; 279191783Srmacklem sip->fs_rtmult = NFS_FABLKSIZE; 280191783Srmacklem sip->fs_wtmax = NFS_MAXDATA; 281191783Srmacklem sip->fs_wtpref = pref; 282191783Srmacklem sip->fs_wtmult = NFS_FABLKSIZE; 283191783Srmacklem sip->fs_dtpref = pref; 284191783Srmacklem sip->fs_maxfilesize = 0xffffffffffffffffull; 285191783Srmacklem sip->fs_timedelta.tv_sec = 0; 286191783Srmacklem sip->fs_timedelta.tv_nsec = 1; 287191783Srmacklem sip->fs_properties = (NFSV3FSINFO_LINK | 288191783Srmacklem NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 289191783Srmacklem NFSV3FSINFO_CANSETTIME); 290191783Srmacklem} 291191783Srmacklem 292224078Szack/* 293224078Szack * Do the pathconf vnode op. 294224078Szack */ 295224078Szackint 296224078Szacknfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, 297224078Szack struct ucred *cred, struct thread *p) 298224078Szack{ 299224078Szack int error; 300224078Szack 301224078Szack error = VOP_PATHCONF(vp, flag, retf); 302224078Szack if (error == EOPNOTSUPP || error == EINVAL) { 303224078Szack /* 304224078Szack * Some file systems return EINVAL for name arguments not 305224078Szack * supported and some return EOPNOTSUPP for this case. 306224078Szack * So the NFSv3 Pathconf RPC doesn't fail for these cases, 307224078Szack * just fake them. 308224078Szack */ 309224078Szack switch (flag) { 310224078Szack case _PC_LINK_MAX: 311224078Szack *retf = LINK_MAX; 312224078Szack break; 313224078Szack case _PC_NAME_MAX: 314224078Szack *retf = NAME_MAX; 315224078Szack break; 316224078Szack case _PC_CHOWN_RESTRICTED: 317224078Szack *retf = 1; 318224078Szack break; 319224078Szack case _PC_NO_TRUNC: 320224078Szack *retf = 1; 321224078Szack break; 322224078Szack default: 323224078Szack /* 324224078Szack * Only happens if a _PC_xxx is added to the server, 325224078Szack * but this isn't updated. 326224078Szack */ 327224078Szack *retf = 0; 328224078Szack printf("nfsrvd pathconf flag=%d not supp\n", flag); 329224078Szack }; 330224078Szack error = 0; 331224078Szack } 332224078Szack return (error); 333224078Szack} 334224078Szack 335191783Srmacklem/* Fake nfsrv_atroot. Just return 0 */ 336191783Srmacklemint 337191783Srmacklemnfsrv_atroot(struct vnode *vp, long *retp) 338191783Srmacklem{ 339191783Srmacklem 340191783Srmacklem return (0); 341191783Srmacklem} 342191783Srmacklem 343191783Srmacklem/* 344191783Srmacklem * Set the credentials to refer to root. 345191783Srmacklem * If only the various BSDen could agree on whether cr_gid is a separate 346191783Srmacklem * field or cr_groups[0]... 347191783Srmacklem */ 348191783Srmacklemvoid 349191783Srmacklemnewnfs_setroot(struct ucred *cred) 350191783Srmacklem{ 351191783Srmacklem 352191783Srmacklem cred->cr_uid = 0; 353191783Srmacklem cred->cr_groups[0] = 0; 354191783Srmacklem cred->cr_ngroups = 1; 355191783Srmacklem} 356191783Srmacklem 357191783Srmacklem/* 358191783Srmacklem * Get the client credential. Used for Renew and recovery. 359191783Srmacklem */ 360191783Srmacklemstruct ucred * 361191783Srmacklemnewnfs_getcred(void) 362191783Srmacklem{ 363191783Srmacklem struct ucred *cred; 364191783Srmacklem struct thread *td = curthread; 365191783Srmacklem 366191783Srmacklem cred = crdup(td->td_ucred); 367191783Srmacklem newnfs_setroot(cred); 368191783Srmacklem return (cred); 369191783Srmacklem} 370191783Srmacklem 371191783Srmacklem/* 372191783Srmacklem * Nfs timer routine 373191783Srmacklem * Call the nfsd's timer function once/sec. 374191783Srmacklem */ 375191783Srmacklemvoid 376191783Srmacklemnewnfs_timer(void *arg) 377191783Srmacklem{ 378191783Srmacklem static time_t lasttime = 0; 379191783Srmacklem /* 380191783Srmacklem * Call the server timer, if set up. 381191783Srmacklem * The argument indicates if it is the next second and therefore 382191783Srmacklem * leases should be checked. 383191783Srmacklem */ 384191783Srmacklem if (lasttime != NFSD_MONOSEC) { 385191783Srmacklem lasttime = NFSD_MONOSEC; 386191783Srmacklem if (nfsd_call_servertimer != NULL) 387191783Srmacklem (*nfsd_call_servertimer)(); 388191783Srmacklem } 389191783Srmacklem callout_reset(&newnfsd_callout, nfscl_ticks, newnfs_timer, NULL); 390191783Srmacklem} 391191783Srmacklem 392191783Srmacklem 393191783Srmacklem/* 394207170Srmacklem * Sleep for a short period of time unless errval == NFSERR_GRACE, where 395207170Srmacklem * the sleep should be for 5 seconds. 396191783Srmacklem * Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on 397191783Srmacklem * an event that never gets a wakeup. Only return EINTR or 0. 398191783Srmacklem */ 399191783Srmacklemint 400207170Srmacklemnfs_catnap(int prio, int errval, const char *wmesg) 401191783Srmacklem{ 402191783Srmacklem static int non_event; 403191783Srmacklem int ret; 404191783Srmacklem 405207170Srmacklem if (errval == NFSERR_GRACE) 406207170Srmacklem ret = tsleep(&non_event, prio, wmesg, 5 * hz); 407207170Srmacklem else 408207170Srmacklem ret = tsleep(&non_event, prio, wmesg, 1); 409191783Srmacklem if (ret != EINTR) 410191783Srmacklem ret = 0; 411191783Srmacklem return (ret); 412191783Srmacklem} 413191783Srmacklem 414191783Srmacklem/* 415191783Srmacklem * Get referral. For now, just fail. 416191783Srmacklem */ 417191783Srmacklemstruct nfsreferral * 418191783Srmacklemnfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno) 419191783Srmacklem{ 420191783Srmacklem 421191783Srmacklem return (NULL); 422191783Srmacklem} 423191783Srmacklem 424191783Srmacklemstatic int 425191783Srmacklemnfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap) 426191783Srmacklem{ 427191783Srmacklem int error; 428191783Srmacklem 429191783Srmacklem error = nfssvc_call(td, uap, td->td_ucred); 430191783Srmacklem return (error); 431191783Srmacklem} 432191783Srmacklem 433191783Srmacklemstatic int 434191783Srmacklemnfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 435191783Srmacklem{ 436191783Srmacklem int error = EINVAL; 437191783Srmacklem struct nfsd_idargs nid; 438191783Srmacklem 439191783Srmacklem if (uap->flag & NFSSVC_IDNAME) { 440191783Srmacklem error = copyin(uap->argp, (caddr_t)&nid, sizeof (nid)); 441191783Srmacklem if (error) 442191783Srmacklem return (error); 443191783Srmacklem error = nfssvc_idname(&nid); 444191783Srmacklem return (error); 445191783Srmacklem } else if (uap->flag & NFSSVC_GETSTATS) { 446191783Srmacklem error = copyout(&newnfsstats, 447191783Srmacklem CAST_USER_ADDR_T(uap->argp), sizeof (newnfsstats)); 448221439Srmacklem if (error == 0) { 449221439Srmacklem if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) { 450221439Srmacklem newnfsstats.attrcache_hits = 0; 451221439Srmacklem newnfsstats.attrcache_misses = 0; 452221439Srmacklem newnfsstats.lookupcache_hits = 0; 453221439Srmacklem newnfsstats.lookupcache_misses = 0; 454221439Srmacklem newnfsstats.direofcache_hits = 0; 455221439Srmacklem newnfsstats.direofcache_misses = 0; 456221439Srmacklem newnfsstats.accesscache_hits = 0; 457221439Srmacklem newnfsstats.accesscache_misses = 0; 458221439Srmacklem newnfsstats.biocache_reads = 0; 459221439Srmacklem newnfsstats.read_bios = 0; 460221439Srmacklem newnfsstats.read_physios = 0; 461221439Srmacklem newnfsstats.biocache_writes = 0; 462221439Srmacklem newnfsstats.write_bios = 0; 463221439Srmacklem newnfsstats.write_physios = 0; 464221439Srmacklem newnfsstats.biocache_readlinks = 0; 465221439Srmacklem newnfsstats.readlink_bios = 0; 466221439Srmacklem newnfsstats.biocache_readdirs = 0; 467221439Srmacklem newnfsstats.readdir_bios = 0; 468221439Srmacklem newnfsstats.rpcretries = 0; 469221439Srmacklem newnfsstats.rpcrequests = 0; 470221439Srmacklem newnfsstats.rpctimeouts = 0; 471221439Srmacklem newnfsstats.rpcunexpected = 0; 472221439Srmacklem newnfsstats.rpcinvalid = 0; 473221439Srmacklem bzero(newnfsstats.rpccnt, 474221439Srmacklem sizeof(newnfsstats.rpccnt)); 475221439Srmacklem } 476221439Srmacklem if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) { 477221439Srmacklem newnfsstats.srvrpc_errs = 0; 478221439Srmacklem newnfsstats.srv_errs = 0; 479221439Srmacklem newnfsstats.srvcache_inproghits = 0; 480221439Srmacklem newnfsstats.srvcache_idemdonehits = 0; 481221439Srmacklem newnfsstats.srvcache_nonidemdonehits = 0; 482221439Srmacklem newnfsstats.srvcache_misses = 0; 483221439Srmacklem newnfsstats.srvcache_tcppeak = 0; 484221439Srmacklem newnfsstats.srvcache_size = 0; 485221439Srmacklem newnfsstats.srvclients = 0; 486221439Srmacklem newnfsstats.srvopenowners = 0; 487221439Srmacklem newnfsstats.srvopens = 0; 488221439Srmacklem newnfsstats.srvlockowners = 0; 489221439Srmacklem newnfsstats.srvlocks = 0; 490221439Srmacklem newnfsstats.srvdelegates = 0; 491221439Srmacklem newnfsstats.clopenowners = 0; 492221439Srmacklem newnfsstats.clopens = 0; 493221439Srmacklem newnfsstats.cllockowners = 0; 494221439Srmacklem newnfsstats.cllocks = 0; 495221439Srmacklem newnfsstats.cldelegates = 0; 496221439Srmacklem newnfsstats.cllocalopenowners = 0; 497221439Srmacklem newnfsstats.cllocalopens = 0; 498221439Srmacklem newnfsstats.cllocallockowners = 0; 499221439Srmacklem newnfsstats.cllocallocks = 0; 500221439Srmacklem bzero(newnfsstats.srvrpccnt, 501221439Srmacklem sizeof(newnfsstats.srvrpccnt)); 502221439Srmacklem bzero(newnfsstats.cbrpccnt, 503221439Srmacklem sizeof(newnfsstats.cbrpccnt)); 504221439Srmacklem } 505221439Srmacklem } 506191783Srmacklem return (error); 507191783Srmacklem } else if (uap->flag & NFSSVC_NFSUSERDPORT) { 508191783Srmacklem u_short sockport; 509191783Srmacklem 510191783Srmacklem error = copyin(uap->argp, (caddr_t)&sockport, 511191783Srmacklem sizeof (u_short)); 512191783Srmacklem if (!error) 513191783Srmacklem error = nfsrv_nfsuserdport(sockport, p); 514191783Srmacklem } else if (uap->flag & NFSSVC_NFSUSERDDELPORT) { 515191783Srmacklem nfsrv_nfsuserddelport(); 516191783Srmacklem error = 0; 517191783Srmacklem } 518191783Srmacklem return (error); 519191783Srmacklem} 520191783Srmacklem 521191783Srmacklem/* 522191783Srmacklem * called by all three modevent routines, so that it gets things 523191783Srmacklem * initialized soon enough. 524191783Srmacklem */ 525191783Srmacklemvoid 526191783Srmacklemnewnfs_portinit(void) 527191783Srmacklem{ 528191783Srmacklem static int inited = 0; 529191783Srmacklem 530191783Srmacklem if (inited) 531191783Srmacklem return; 532191783Srmacklem inited = 1; 533191783Srmacklem /* Initialize SMP locks used by both client and server. */ 534191783Srmacklem mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF); 535191783Srmacklem mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF); 536191783Srmacklem} 537191783Srmacklem 538192898Srmacklem/* 539192898Srmacklem * Determine if the file system supports NFSv4 ACLs. 540192898Srmacklem * Return 1 if it does, 0 otherwise. 541192898Srmacklem */ 542192898Srmacklemint 543220648Srmacklemnfs_supportsnfsv4acls(struct vnode *vp) 544192898Srmacklem{ 545220648Srmacklem int error; 546220648Srmacklem register_t retval; 547192898Srmacklem 548220648Srmacklem ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls"); 549220648Srmacklem 550220648Srmacklem if (nfsrv_useacl == 0) 551192898Srmacklem return (0); 552220648Srmacklem error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval); 553220648Srmacklem if (error == 0 && retval != 0) 554192898Srmacklem return (1); 555192898Srmacklem return (0); 556192898Srmacklem} 557192898Srmacklem 558191783Srmacklemextern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *); 559191783Srmacklem 560191783Srmacklem/* 561191783Srmacklem * Called once to initialize data structures... 562191783Srmacklem */ 563191783Srmacklemstatic int 564191783Srmacklemnfscommon_modevent(module_t mod, int type, void *data) 565191783Srmacklem{ 566191783Srmacklem int error = 0; 567191783Srmacklem static int loaded = 0; 568191783Srmacklem 569191783Srmacklem switch (type) { 570191783Srmacklem case MOD_LOAD: 571191783Srmacklem if (loaded) 572191783Srmacklem return (0); 573191783Srmacklem newnfs_portinit(); 574191783Srmacklem mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF); 575191783Srmacklem mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF); 576191783Srmacklem mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF); 577191783Srmacklem mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF); 578191783Srmacklem mtx_init(&nfsrv_nfsuserdsock.nr_mtx, "nfsuserd", NULL, 579191783Srmacklem MTX_DEF); 580191783Srmacklem callout_init(&newnfsd_callout, CALLOUT_MPSAFE); 581191783Srmacklem newnfs_init(); 582191783Srmacklem nfsd_call_nfscommon = nfssvc_nfscommon; 583191783Srmacklem loaded = 1; 584191783Srmacklem break; 585191783Srmacklem 586191783Srmacklem case MOD_UNLOAD: 587191783Srmacklem if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != 0 || 588191783Srmacklem nfs_numnfscbd != 0) { 589191783Srmacklem error = EBUSY; 590191783Srmacklem break; 591191783Srmacklem } 592191783Srmacklem 593191783Srmacklem nfsd_call_nfscommon = NULL; 594191783Srmacklem callout_drain(&newnfsd_callout); 595191783Srmacklem /* and get rid of the mutexes */ 596191783Srmacklem mtx_destroy(&nfs_nameid_mutex); 597191783Srmacklem mtx_destroy(&newnfsd_mtx); 598191783Srmacklem mtx_destroy(&nfs_state_mutex); 599191783Srmacklem mtx_destroy(&nfs_sockl_mutex); 600191783Srmacklem mtx_destroy(&nfs_slock_mutex); 601191783Srmacklem mtx_destroy(&nfs_req_mutex); 602191783Srmacklem mtx_destroy(&nfsrv_nfsuserdsock.nr_mtx); 603191783Srmacklem loaded = 0; 604191783Srmacklem break; 605191783Srmacklem default: 606191783Srmacklem error = EOPNOTSUPP; 607191783Srmacklem break; 608191783Srmacklem } 609191783Srmacklem return error; 610191783Srmacklem} 611191783Srmacklemstatic moduledata_t nfscommon_mod = { 612191783Srmacklem "nfscommon", 613191783Srmacklem nfscommon_modevent, 614191783Srmacklem NULL, 615191783Srmacklem}; 616191783SrmacklemDECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY); 617191783Srmacklem 618191783Srmacklem/* So that loader and kldload(2) can find us, wherever we are.. */ 619191783SrmacklemMODULE_VERSION(nfscommon, 1); 620191783SrmacklemMODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1); 621191783SrmacklemMODULE_DEPEND(nfscommon, krpc, 1, 1, 1); 622191783Srmacklem 623