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$"); 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 53191783Srmacklemextern int nfscl_ticks; 54191783Srmacklemextern int nfsrv_nfsuserd; 55191783Srmacklemextern struct nfssockreq nfsrv_nfsuserdsock; 56191783Srmacklemextern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, 57191783Srmacklem struct thread *); 58191783Srmacklemextern int nfsrv_useacl; 59191783Srmacklemstruct mount nfsv4root_mnt; 60191783Srmacklemint newnfs_numnfsd = 0; 61191783Srmacklemstruct nfsstats newnfsstats; 62191783Srmacklemint nfs_numnfscbd = 0; 63240289Srmacklemint nfscl_debuglevel = 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"); 80240289SrmacklemSYSCTL_INT(_vfs_nfs, OID_AUTO, debuglevel, CTLFLAG_RW, &nfscl_debuglevel, 81240289Srmacklem 0, "Debug level for new nfs client"); 82191783Srmacklem 83191783Srmacklem/* 84191783Srmacklem * Defines for malloc 85191783Srmacklem * (Here for FreeBSD, since they allocate storage.) 86191783Srmacklem */ 87191783SrmacklemMALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache"); 88191783SrmacklemMALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id"); 89205941SrmacklemMALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", 90205941Srmacklem "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); 91191783SrmacklemMALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock"); 92191783SrmacklemMALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file"); 93191783SrmacklemMALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string"); 94191783SrmacklemMALLOC_DEFINE(M_NEWNFSUSERGROUP, "NFSD usrgroup", "NFSD V4 User/group map"); 95191783SrmacklemMALLOC_DEFINE(M_NEWNFSDREQ, "NFS req", "NFS request header"); 96191783SrmacklemMALLOC_DEFINE(M_NEWNFSFH, "NFS fh", "NFS file handle"); 97191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLOWNER, "NFSCL owner", "NFSCL Open Owner"); 98191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLOPEN, "NFSCL open", "NFSCL Open"); 99191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLDELEG, "NFSCL deleg", "NFSCL Delegation"); 100191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLCLIENT, "NFSCL client", "NFSCL Client"); 101191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner"); 102191783SrmacklemMALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock"); 103191783SrmacklemMALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "New nfs vnode"); 104191783SrmacklemMALLOC_DEFINE(M_NEWNFSDIRECTIO, "NEWdirectio", "New nfs Direct IO buffer"); 105205941SrmacklemMALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroffdiroff", 106205941Srmacklem "New NFS directory offset data"); 107205941SrmacklemMALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", 108205941Srmacklem "New NFS local lock rollback"); 109244042SrmacklemMALLOC_DEFINE(M_NEWNFSLAYOUT, "NFSCL layout", "NFSv4.1 Layout"); 110244042SrmacklemMALLOC_DEFINE(M_NEWNFSFLAYOUT, "NFSCL flayout", "NFSv4.1 File Layout"); 111244042SrmacklemMALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL devinfo", "NFSv4.1 Device Info"); 112244042SrmacklemMALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req"); 113244042SrmacklemMALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session"); 114244042SrmacklemMALLOC_DEFINE(M_NEWNFSLAYRECALL, "NFSCL layrecall", "NFSv4.1 Layout Recall"); 115269398SrmacklemMALLOC_DEFINE(M_NEWNFSDSESSION, "NFSD session", "NFSD Session for a client"); 116191783Srmacklem 117191783Srmacklem/* 118191783Srmacklem * Definition of mutex locks. 119191783Srmacklem * newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list 120191783Srmacklem * and assorted other nfsd structures. 121191783Srmacklem */ 122191783Srmacklemstruct mtx newnfsd_mtx; 123191783Srmacklemstruct mtx nfs_sockl_mutex; 124191783Srmacklemstruct mtx nfs_state_mutex; 125191783Srmacklemstruct mtx nfs_nameid_mutex; 126191783Srmacklemstruct mtx nfs_req_mutex; 127191783Srmacklemstruct mtx nfs_slock_mutex; 128191783Srmacklem 129191783Srmacklem/* local functions */ 130191783Srmacklemstatic int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); 131191783Srmacklem 132205572Srmacklem#ifdef __NO_STRICT_ALIGNMENT 133191783Srmacklem/* 134191783Srmacklem * These architectures don't need re-alignment, so just return. 135191783Srmacklem */ 136249592Skenint 137249592Skennewnfs_realign(struct mbuf **pm, int how) 138191783Srmacklem{ 139191783Srmacklem 140249592Sken return (0); 141191783Srmacklem} 142205572Srmacklem#else /* !__NO_STRICT_ALIGNMENT */ 143191783Srmacklem/* 144192695Srmacklem * newnfs_realign: 145191783Srmacklem * 146191783Srmacklem * Check for badly aligned mbuf data and realign by copying the unaligned 147191783Srmacklem * portion of the data into a new mbuf chain and freeing the portions 148191783Srmacklem * of the old chain that were replaced. 149191783Srmacklem * 150191783Srmacklem * We cannot simply realign the data within the existing mbuf chain 151191783Srmacklem * because the underlying buffers may contain other rpc commands and 152191783Srmacklem * we cannot afford to overwrite them. 153191783Srmacklem * 154191783Srmacklem * We would prefer to avoid this situation entirely. The situation does 155191783Srmacklem * not occur with NFS/UDP and is supposed to only occassionally occur 156191783Srmacklem * with TCP. Use vfs.nfs.realign_count and realign_test to check this. 157192695Srmacklem * 158191783Srmacklem */ 159249592Skenint 160249592Skennewnfs_realign(struct mbuf **pm, int how) 161191783Srmacklem{ 162192695Srmacklem struct mbuf *m, *n; 163192695Srmacklem int off, space; 164191783Srmacklem 165191783Srmacklem ++nfs_realign_test; 166191783Srmacklem while ((m = *pm) != NULL) { 167191783Srmacklem if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { 168192695Srmacklem /* 169192695Srmacklem * NB: we can't depend on m_pkthdr.len to help us 170192695Srmacklem * decide what to do here. May not be worth doing 171192695Srmacklem * the m_length calculation as m_copyback will 172192695Srmacklem * expand the mbuf chain below as needed. 173192695Srmacklem */ 174192695Srmacklem space = m_length(m, NULL); 175192695Srmacklem if (space >= MINCLSIZE) { 176192695Srmacklem /* NB: m_copyback handles space > MCLBYTES */ 177249592Sken n = m_getcl(how, MT_DATA, 0); 178192695Srmacklem } else 179249592Sken n = m_get(how, MT_DATA); 180192695Srmacklem if (n == NULL) 181249592Sken return (ENOMEM); 182192695Srmacklem /* 183192695Srmacklem * Align the remainder of the mbuf chain. 184192695Srmacklem */ 185192695Srmacklem n->m_len = 0; 186192695Srmacklem off = 0; 187192695Srmacklem while (m != NULL) { 188192695Srmacklem m_copyback(n, off, m->m_len, mtod(m, caddr_t)); 189192695Srmacklem off += m->m_len; 190192695Srmacklem m = m->m_next; 191191783Srmacklem } 192192695Srmacklem m_freem(*pm); 193192695Srmacklem *pm = n; 194192695Srmacklem ++nfs_realign_count; 195191783Srmacklem break; 196191783Srmacklem } 197191783Srmacklem pm = &m->m_next; 198191783Srmacklem } 199249592Sken 200249592Sken return (0); 201191783Srmacklem} 202205572Srmacklem#endif /* __NO_STRICT_ALIGNMENT */ 203191783Srmacklem 204191783Srmacklem#ifdef notdef 205191783Srmacklemstatic void 206191783Srmacklemnfsrv_object_create(struct vnode *vp, struct thread *td) 207191783Srmacklem{ 208191783Srmacklem 209191783Srmacklem if (vp == NULL || vp->v_type != VREG) 210191783Srmacklem return; 211191783Srmacklem (void) vfs_object_create(vp, td, td->td_ucred); 212191783Srmacklem} 213191783Srmacklem#endif 214191783Srmacklem 215191783Srmacklem/* 216191783Srmacklem * Look up a file name. Basically just initialize stuff and call namei(). 217191783Srmacklem */ 218191783Srmacklemint 219191783Srmacklemnfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p) 220191783Srmacklem{ 221191783Srmacklem int error; 222191783Srmacklem 223241896Skib NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fname, 224210268Srmacklem p); 225191783Srmacklem error = namei(ndp); 226191783Srmacklem if (!error) { 227191783Srmacklem NDFREE(ndp, NDF_ONLY_PNBUF); 228191783Srmacklem } 229191783Srmacklem return (error); 230191783Srmacklem} 231191783Srmacklem 232191783Srmacklem/* 233191783Srmacklem * Copy NFS uid, gids to the cred structure. 234191783Srmacklem */ 235191783Srmacklemvoid 236191783Srmacklemnewnfs_copycred(struct nfscred *nfscr, struct ucred *cr) 237191783Srmacklem{ 238191783Srmacklem 239206688Srmacklem KASSERT(nfscr->nfsc_ngroups >= 0, 240206688Srmacklem ("newnfs_copycred: negative nfsc_ngroups")); 241191783Srmacklem cr->cr_uid = nfscr->nfsc_uid; 242194498Sbrooks crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); 243191783Srmacklem} 244191783Srmacklem 245191783Srmacklem/* 246191783Srmacklem * Map args from nfsmsleep() to msleep(). 247191783Srmacklem */ 248191783Srmacklemint 249191783Srmacklemnfsmsleep(void *chan, void *mutex, int prio, const char *wmesg, 250191783Srmacklem struct timespec *ts) 251191783Srmacklem{ 252191783Srmacklem u_int64_t nsecval; 253191783Srmacklem int error, timeo; 254191783Srmacklem 255191783Srmacklem if (ts) { 256191783Srmacklem timeo = hz * ts->tv_sec; 257191783Srmacklem nsecval = (u_int64_t)ts->tv_nsec; 258191783Srmacklem nsecval = ((nsecval * ((u_int64_t)hz)) + 500000000) / 259191783Srmacklem 1000000000; 260191783Srmacklem timeo += (int)nsecval; 261191783Srmacklem } else { 262191783Srmacklem timeo = 0; 263191783Srmacklem } 264191783Srmacklem error = msleep(chan, (struct mtx *)mutex, prio, wmesg, timeo); 265191783Srmacklem return (error); 266191783Srmacklem} 267191783Srmacklem 268191783Srmacklem/* 269191783Srmacklem * Get the file system info for the server. For now, just assume FFS. 270191783Srmacklem */ 271191783Srmacklemvoid 272191783Srmacklemnfsvno_getfs(struct nfsfsinfo *sip, int isdgram) 273191783Srmacklem{ 274191783Srmacklem int pref; 275191783Srmacklem 276191783Srmacklem /* 277191783Srmacklem * XXX 278191783Srmacklem * There should be file system VFS OP(s) to get this information. 279191783Srmacklem * For now, assume ufs. 280191783Srmacklem */ 281191783Srmacklem if (isdgram) 282191783Srmacklem pref = NFS_MAXDGRAMDATA; 283191783Srmacklem else 284191783Srmacklem pref = NFS_MAXDATA; 285191783Srmacklem sip->fs_rtmax = NFS_MAXDATA; 286191783Srmacklem sip->fs_rtpref = pref; 287191783Srmacklem sip->fs_rtmult = NFS_FABLKSIZE; 288191783Srmacklem sip->fs_wtmax = NFS_MAXDATA; 289191783Srmacklem sip->fs_wtpref = pref; 290191783Srmacklem sip->fs_wtmult = NFS_FABLKSIZE; 291191783Srmacklem sip->fs_dtpref = pref; 292191783Srmacklem sip->fs_maxfilesize = 0xffffffffffffffffull; 293191783Srmacklem sip->fs_timedelta.tv_sec = 0; 294191783Srmacklem sip->fs_timedelta.tv_nsec = 1; 295191783Srmacklem sip->fs_properties = (NFSV3FSINFO_LINK | 296191783Srmacklem NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 297191783Srmacklem NFSV3FSINFO_CANSETTIME); 298191783Srmacklem} 299191783Srmacklem 300224078Szack/* 301224078Szack * Do the pathconf vnode op. 302224078Szack */ 303224078Szackint 304224078Szacknfsvno_pathconf(struct vnode *vp, int flag, register_t *retf, 305224078Szack struct ucred *cred, struct thread *p) 306224078Szack{ 307224078Szack int error; 308224078Szack 309224078Szack error = VOP_PATHCONF(vp, flag, retf); 310224078Szack if (error == EOPNOTSUPP || error == EINVAL) { 311224078Szack /* 312224078Szack * Some file systems return EINVAL for name arguments not 313224078Szack * supported and some return EOPNOTSUPP for this case. 314224078Szack * So the NFSv3 Pathconf RPC doesn't fail for these cases, 315224078Szack * just fake them. 316224078Szack */ 317224078Szack switch (flag) { 318224078Szack case _PC_LINK_MAX: 319224078Szack *retf = LINK_MAX; 320224078Szack break; 321224078Szack case _PC_NAME_MAX: 322224078Szack *retf = NAME_MAX; 323224078Szack break; 324224078Szack case _PC_CHOWN_RESTRICTED: 325224078Szack *retf = 1; 326224078Szack break; 327224078Szack case _PC_NO_TRUNC: 328224078Szack *retf = 1; 329224078Szack break; 330224078Szack default: 331224078Szack /* 332224078Szack * Only happens if a _PC_xxx is added to the server, 333224078Szack * but this isn't updated. 334224078Szack */ 335224078Szack *retf = 0; 336224078Szack printf("nfsrvd pathconf flag=%d not supp\n", flag); 337224078Szack }; 338224078Szack error = 0; 339224078Szack } 340224086Szack NFSEXITCODE(error); 341224078Szack return (error); 342224078Szack} 343224078Szack 344191783Srmacklem/* Fake nfsrv_atroot. Just return 0 */ 345191783Srmacklemint 346191783Srmacklemnfsrv_atroot(struct vnode *vp, long *retp) 347191783Srmacklem{ 348191783Srmacklem 349191783Srmacklem return (0); 350191783Srmacklem} 351191783Srmacklem 352191783Srmacklem/* 353191783Srmacklem * Set the credentials to refer to root. 354191783Srmacklem * If only the various BSDen could agree on whether cr_gid is a separate 355191783Srmacklem * field or cr_groups[0]... 356191783Srmacklem */ 357191783Srmacklemvoid 358191783Srmacklemnewnfs_setroot(struct ucred *cred) 359191783Srmacklem{ 360191783Srmacklem 361191783Srmacklem cred->cr_uid = 0; 362191783Srmacklem cred->cr_groups[0] = 0; 363191783Srmacklem cred->cr_ngroups = 1; 364191783Srmacklem} 365191783Srmacklem 366191783Srmacklem/* 367191783Srmacklem * Get the client credential. Used for Renew and recovery. 368191783Srmacklem */ 369191783Srmacklemstruct ucred * 370191783Srmacklemnewnfs_getcred(void) 371191783Srmacklem{ 372191783Srmacklem struct ucred *cred; 373191783Srmacklem struct thread *td = curthread; 374191783Srmacklem 375191783Srmacklem cred = crdup(td->td_ucred); 376191783Srmacklem newnfs_setroot(cred); 377191783Srmacklem return (cred); 378191783Srmacklem} 379191783Srmacklem 380191783Srmacklem/* 381191783Srmacklem * Nfs timer routine 382191783Srmacklem * Call the nfsd's timer function once/sec. 383191783Srmacklem */ 384191783Srmacklemvoid 385191783Srmacklemnewnfs_timer(void *arg) 386191783Srmacklem{ 387191783Srmacklem static time_t lasttime = 0; 388191783Srmacklem /* 389191783Srmacklem * Call the server timer, if set up. 390191783Srmacklem * The argument indicates if it is the next second and therefore 391191783Srmacklem * leases should be checked. 392191783Srmacklem */ 393191783Srmacklem if (lasttime != NFSD_MONOSEC) { 394191783Srmacklem lasttime = NFSD_MONOSEC; 395191783Srmacklem if (nfsd_call_servertimer != NULL) 396191783Srmacklem (*nfsd_call_servertimer)(); 397191783Srmacklem } 398191783Srmacklem callout_reset(&newnfsd_callout, nfscl_ticks, newnfs_timer, NULL); 399191783Srmacklem} 400191783Srmacklem 401191783Srmacklem 402191783Srmacklem/* 403207170Srmacklem * Sleep for a short period of time unless errval == NFSERR_GRACE, where 404207170Srmacklem * the sleep should be for 5 seconds. 405191783Srmacklem * Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on 406191783Srmacklem * an event that never gets a wakeup. Only return EINTR or 0. 407191783Srmacklem */ 408191783Srmacklemint 409207170Srmacklemnfs_catnap(int prio, int errval, const char *wmesg) 410191783Srmacklem{ 411191783Srmacklem static int non_event; 412191783Srmacklem int ret; 413191783Srmacklem 414207170Srmacklem if (errval == NFSERR_GRACE) 415207170Srmacklem ret = tsleep(&non_event, prio, wmesg, 5 * hz); 416207170Srmacklem else 417207170Srmacklem ret = tsleep(&non_event, prio, wmesg, 1); 418191783Srmacklem if (ret != EINTR) 419191783Srmacklem ret = 0; 420191783Srmacklem return (ret); 421191783Srmacklem} 422191783Srmacklem 423191783Srmacklem/* 424191783Srmacklem * Get referral. For now, just fail. 425191783Srmacklem */ 426191783Srmacklemstruct nfsreferral * 427191783Srmacklemnfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno) 428191783Srmacklem{ 429191783Srmacklem 430191783Srmacklem return (NULL); 431191783Srmacklem} 432191783Srmacklem 433191783Srmacklemstatic int 434191783Srmacklemnfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap) 435191783Srmacklem{ 436191783Srmacklem int error; 437191783Srmacklem 438191783Srmacklem error = nfssvc_call(td, uap, td->td_ucred); 439224086Szack NFSEXITCODE(error); 440191783Srmacklem return (error); 441191783Srmacklem} 442191783Srmacklem 443191783Srmacklemstatic int 444191783Srmacklemnfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 445191783Srmacklem{ 446191783Srmacklem int error = EINVAL; 447191783Srmacklem struct nfsd_idargs nid; 448191783Srmacklem 449191783Srmacklem if (uap->flag & NFSSVC_IDNAME) { 450191783Srmacklem error = copyin(uap->argp, (caddr_t)&nid, sizeof (nid)); 451191783Srmacklem if (error) 452224086Szack goto out; 453191783Srmacklem error = nfssvc_idname(&nid); 454224086Szack goto out; 455191783Srmacklem } else if (uap->flag & NFSSVC_GETSTATS) { 456191783Srmacklem error = copyout(&newnfsstats, 457191783Srmacklem CAST_USER_ADDR_T(uap->argp), sizeof (newnfsstats)); 458221439Srmacklem if (error == 0) { 459221439Srmacklem if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) { 460221439Srmacklem newnfsstats.attrcache_hits = 0; 461221439Srmacklem newnfsstats.attrcache_misses = 0; 462221439Srmacklem newnfsstats.lookupcache_hits = 0; 463221439Srmacklem newnfsstats.lookupcache_misses = 0; 464221439Srmacklem newnfsstats.direofcache_hits = 0; 465221439Srmacklem newnfsstats.direofcache_misses = 0; 466221439Srmacklem newnfsstats.accesscache_hits = 0; 467221439Srmacklem newnfsstats.accesscache_misses = 0; 468221439Srmacklem newnfsstats.biocache_reads = 0; 469221439Srmacklem newnfsstats.read_bios = 0; 470221439Srmacklem newnfsstats.read_physios = 0; 471221439Srmacklem newnfsstats.biocache_writes = 0; 472221439Srmacklem newnfsstats.write_bios = 0; 473221439Srmacklem newnfsstats.write_physios = 0; 474221439Srmacklem newnfsstats.biocache_readlinks = 0; 475221439Srmacklem newnfsstats.readlink_bios = 0; 476221439Srmacklem newnfsstats.biocache_readdirs = 0; 477221439Srmacklem newnfsstats.readdir_bios = 0; 478221439Srmacklem newnfsstats.rpcretries = 0; 479221439Srmacklem newnfsstats.rpcrequests = 0; 480221439Srmacklem newnfsstats.rpctimeouts = 0; 481221439Srmacklem newnfsstats.rpcunexpected = 0; 482221439Srmacklem newnfsstats.rpcinvalid = 0; 483221439Srmacklem bzero(newnfsstats.rpccnt, 484221439Srmacklem sizeof(newnfsstats.rpccnt)); 485221439Srmacklem } 486221439Srmacklem if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) { 487221439Srmacklem newnfsstats.srvrpc_errs = 0; 488221439Srmacklem newnfsstats.srv_errs = 0; 489221439Srmacklem newnfsstats.srvcache_inproghits = 0; 490221439Srmacklem newnfsstats.srvcache_idemdonehits = 0; 491221439Srmacklem newnfsstats.srvcache_nonidemdonehits = 0; 492221439Srmacklem newnfsstats.srvcache_misses = 0; 493221439Srmacklem newnfsstats.srvcache_tcppeak = 0; 494221439Srmacklem newnfsstats.srvclients = 0; 495221439Srmacklem newnfsstats.srvopenowners = 0; 496221439Srmacklem newnfsstats.srvopens = 0; 497221439Srmacklem newnfsstats.srvlockowners = 0; 498221439Srmacklem newnfsstats.srvlocks = 0; 499221439Srmacklem newnfsstats.srvdelegates = 0; 500221439Srmacklem newnfsstats.clopenowners = 0; 501221439Srmacklem newnfsstats.clopens = 0; 502221439Srmacklem newnfsstats.cllockowners = 0; 503221439Srmacklem newnfsstats.cllocks = 0; 504221439Srmacklem newnfsstats.cldelegates = 0; 505221439Srmacklem newnfsstats.cllocalopenowners = 0; 506221439Srmacklem newnfsstats.cllocalopens = 0; 507221439Srmacklem newnfsstats.cllocallockowners = 0; 508221439Srmacklem newnfsstats.cllocallocks = 0; 509221439Srmacklem bzero(newnfsstats.srvrpccnt, 510221439Srmacklem sizeof(newnfsstats.srvrpccnt)); 511221439Srmacklem bzero(newnfsstats.cbrpccnt, 512221439Srmacklem sizeof(newnfsstats.cbrpccnt)); 513221439Srmacklem } 514221439Srmacklem } 515224086Szack goto out; 516191783Srmacklem } else if (uap->flag & NFSSVC_NFSUSERDPORT) { 517191783Srmacklem u_short sockport; 518191783Srmacklem 519191783Srmacklem error = copyin(uap->argp, (caddr_t)&sockport, 520191783Srmacklem sizeof (u_short)); 521191783Srmacklem if (!error) 522191783Srmacklem error = nfsrv_nfsuserdport(sockport, p); 523191783Srmacklem } else if (uap->flag & NFSSVC_NFSUSERDDELPORT) { 524191783Srmacklem nfsrv_nfsuserddelport(); 525191783Srmacklem error = 0; 526191783Srmacklem } 527224086Szack 528224086Szackout: 529224086Szack NFSEXITCODE(error); 530191783Srmacklem return (error); 531191783Srmacklem} 532191783Srmacklem 533191783Srmacklem/* 534191783Srmacklem * called by all three modevent routines, so that it gets things 535191783Srmacklem * initialized soon enough. 536191783Srmacklem */ 537191783Srmacklemvoid 538191783Srmacklemnewnfs_portinit(void) 539191783Srmacklem{ 540191783Srmacklem static int inited = 0; 541191783Srmacklem 542191783Srmacklem if (inited) 543191783Srmacklem return; 544191783Srmacklem inited = 1; 545191783Srmacklem /* Initialize SMP locks used by both client and server. */ 546191783Srmacklem mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF); 547191783Srmacklem mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF); 548191783Srmacklem} 549191783Srmacklem 550192898Srmacklem/* 551192898Srmacklem * Determine if the file system supports NFSv4 ACLs. 552192898Srmacklem * Return 1 if it does, 0 otherwise. 553192898Srmacklem */ 554192898Srmacklemint 555220648Srmacklemnfs_supportsnfsv4acls(struct vnode *vp) 556192898Srmacklem{ 557220648Srmacklem int error; 558220648Srmacklem register_t retval; 559192898Srmacklem 560220648Srmacklem ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls"); 561220648Srmacklem 562220648Srmacklem if (nfsrv_useacl == 0) 563192898Srmacklem return (0); 564224121Szack error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval); 565220648Srmacklem if (error == 0 && retval != 0) 566192898Srmacklem return (1); 567192898Srmacklem return (0); 568192898Srmacklem} 569192898Srmacklem 570191783Srmacklemextern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *); 571191783Srmacklem 572191783Srmacklem/* 573191783Srmacklem * Called once to initialize data structures... 574191783Srmacklem */ 575191783Srmacklemstatic int 576191783Srmacklemnfscommon_modevent(module_t mod, int type, void *data) 577191783Srmacklem{ 578191783Srmacklem int error = 0; 579191783Srmacklem static int loaded = 0; 580191783Srmacklem 581191783Srmacklem switch (type) { 582191783Srmacklem case MOD_LOAD: 583191783Srmacklem if (loaded) 584224086Szack goto out; 585191783Srmacklem newnfs_portinit(); 586191783Srmacklem mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF); 587191783Srmacklem mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF); 588191783Srmacklem mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF); 589191783Srmacklem mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF); 590191783Srmacklem mtx_init(&nfsrv_nfsuserdsock.nr_mtx, "nfsuserd", NULL, 591191783Srmacklem MTX_DEF); 592191783Srmacklem callout_init(&newnfsd_callout, CALLOUT_MPSAFE); 593191783Srmacklem newnfs_init(); 594191783Srmacklem nfsd_call_nfscommon = nfssvc_nfscommon; 595191783Srmacklem loaded = 1; 596191783Srmacklem break; 597191783Srmacklem 598191783Srmacklem case MOD_UNLOAD: 599191783Srmacklem if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != 0 || 600191783Srmacklem nfs_numnfscbd != 0) { 601191783Srmacklem error = EBUSY; 602191783Srmacklem break; 603191783Srmacklem } 604191783Srmacklem 605191783Srmacklem nfsd_call_nfscommon = NULL; 606191783Srmacklem callout_drain(&newnfsd_callout); 607191783Srmacklem /* and get rid of the mutexes */ 608191783Srmacklem mtx_destroy(&nfs_nameid_mutex); 609191783Srmacklem mtx_destroy(&newnfsd_mtx); 610191783Srmacklem mtx_destroy(&nfs_state_mutex); 611191783Srmacklem mtx_destroy(&nfs_sockl_mutex); 612191783Srmacklem mtx_destroy(&nfs_slock_mutex); 613191783Srmacklem mtx_destroy(&nfs_req_mutex); 614191783Srmacklem mtx_destroy(&nfsrv_nfsuserdsock.nr_mtx); 615191783Srmacklem loaded = 0; 616191783Srmacklem break; 617191783Srmacklem default: 618191783Srmacklem error = EOPNOTSUPP; 619191783Srmacklem break; 620191783Srmacklem } 621224086Szack 622224086Szackout: 623224086Szack NFSEXITCODE(error); 624191783Srmacklem return error; 625191783Srmacklem} 626191783Srmacklemstatic moduledata_t nfscommon_mod = { 627191783Srmacklem "nfscommon", 628191783Srmacklem nfscommon_modevent, 629191783Srmacklem NULL, 630191783Srmacklem}; 631191783SrmacklemDECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY); 632191783Srmacklem 633191783Srmacklem/* So that loader and kldload(2) can find us, wherever we are.. */ 634191783SrmacklemMODULE_VERSION(nfscommon, 1); 635191783SrmacklemMODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1); 636191783SrmacklemMODULE_DEPEND(nfscommon, krpc, 1, 1, 1); 637191783Srmacklem 638