1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 /* 40 * Functions that need to be different for different versions of BSD 41 * kernel should be kept here, along with any global storage specific 42 * to this BSD variant. 43 */ 44 #include <fs/nfs/nfsport.h> 45 #include <sys/smp.h> 46 #include <sys/sysctl.h> 47 #include <sys/taskqueue.h> 48 #include <rpc/rpc_com.h> 49 #include <vm/vm.h> 50 #include <vm/vm_object.h> 51 #include <vm/vm_page.h> 52 #include <vm/vm_param.h> 53 #include <vm/vm_map.h> 54 #include <vm/vm_kern.h> 55 #include <vm/vm_extern.h> 56 #include <vm/uma.h> 57 58 extern int nfscl_ticks; 59 extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *, 60 struct thread *); 61 extern int nfsrv_useacl; 62 int newnfs_numnfsd = 0; 63 struct nfsstatsv1 nfsstatsv1; 64 int nfs_numnfscbd = 0; 65 int nfscl_debuglevel = 0; 66 char nfsv4_callbackaddr[INET6_ADDRSTRLEN]; 67 int nfsrv_lughashsize = 100; 68 struct mtx nfsrv_dslock_mtx; 69 struct nfsdevicehead nfsrv_devidhead; 70 volatile int nfsrv_devidcnt = 0; 71 void (*ncl_call_invalcaches)(struct vnode *) = NULL; 72 vop_advlock_t *nfs_advlock_p = NULL; 73 vop_reclaim_t *nfs_reclaim_p = NULL; 74 uint32_t nfs_srvmaxio = NFS_SRVMAXIO; 75 76 NFSD_VNET_DEFINE(struct nfsstatsv1 *, nfsstatsv1_p); 77 78 NFSD_VNET_DECLARE(struct nfssockreq, nfsrv_nfsuserdsock); 79 NFSD_VNET_DECLARE(nfsuserd_state, nfsrv_nfsuserd); 80 81 int nfs_pnfsio(task_fn_t *, void *); 82 83 static int nfs_realign_test; 84 static int nfs_realign_count; 85 static struct ext_nfsstats oldnfsstats; 86 static struct nfsstatsov1 nfsstatsov1; 87 88 SYSCTL_NODE(_vfs, OID_AUTO, nfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 89 "NFS filesystem"); 90 SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 91 0, "Number of realign tests done"); 92 SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 93 0, "Number of mbuf realignments done"); 94 SYSCTL_STRING(_vfs_nfs, OID_AUTO, callback_addr, CTLFLAG_RW, 95 nfsv4_callbackaddr, sizeof(nfsv4_callbackaddr), 96 "NFSv4 callback addr for server to use"); 97 SYSCTL_INT(_vfs_nfs, OID_AUTO, debuglevel, CTLFLAG_RW, &nfscl_debuglevel, 98 0, "Debug level for NFS client"); 99 SYSCTL_INT(_vfs_nfs, OID_AUTO, userhashsize, CTLFLAG_RDTUN, &nfsrv_lughashsize, 100 0, "Size of hash tables for uid/name mapping"); 101 int nfs_pnfsiothreads = -1; 102 SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsiothreads, CTLFLAG_RW, &nfs_pnfsiothreads, 103 0, "Number of pNFS mirror I/O threads"); 104 105 /* 106 * Defines for malloc 107 * (Here for FreeBSD, since they allocate storage.) 108 */ 109 MALLOC_DEFINE(M_NEWNFSRVCACHE, "NFSD srvcache", "NFSD Server Request Cache"); 110 MALLOC_DEFINE(M_NEWNFSDCLIENT, "NFSD V4client", "NFSD V4 Client Id"); 111 MALLOC_DEFINE(M_NEWNFSDSTATE, "NFSD V4state", 112 "NFSD V4 State (Openowner, Open, Lockowner, Delegation"); 113 MALLOC_DEFINE(M_NEWNFSDLOCK, "NFSD V4lock", "NFSD V4 byte range lock"); 114 MALLOC_DEFINE(M_NEWNFSDLOCKFILE, "NFSD lckfile", "NFSD Open/Lock file"); 115 MALLOC_DEFINE(M_NEWNFSSTRING, "NFSD string", "NFSD V4 long string"); 116 MALLOC_DEFINE(M_NEWNFSUSERGROUP, "NFSD usrgroup", "NFSD V4 User/group map"); 117 MALLOC_DEFINE(M_NEWNFSDREQ, "NFS req", "NFS request header"); 118 MALLOC_DEFINE(M_NEWNFSFH, "NFS fh", "NFS file handle"); 119 MALLOC_DEFINE(M_NEWNFSCLOWNER, "NFSCL owner", "NFSCL Open Owner"); 120 MALLOC_DEFINE(M_NEWNFSCLOPEN, "NFSCL open", "NFSCL Open"); 121 MALLOC_DEFINE(M_NEWNFSCLDELEG, "NFSCL deleg", "NFSCL Delegation"); 122 MALLOC_DEFINE(M_NEWNFSCLCLIENT, "NFSCL client", "NFSCL Client"); 123 MALLOC_DEFINE(M_NEWNFSCLLOCKOWNER, "NFSCL lckown", "NFSCL Lock Owner"); 124 MALLOC_DEFINE(M_NEWNFSCLLOCK, "NFSCL lck", "NFSCL Lock"); 125 MALLOC_DEFINE(M_NEWNFSV4NODE, "NEWNFSnode", "NFS vnode"); 126 MALLOC_DEFINE(M_NEWNFSDIRECTIO, "NEWdirectio", "NFS Direct IO buffer"); 127 MALLOC_DEFINE(M_NEWNFSDIROFF, "NFSCL diroff", 128 "NFS directory offset data"); 129 MALLOC_DEFINE(M_NEWNFSDROLLBACK, "NFSD rollback", 130 "NFS local lock rollback"); 131 MALLOC_DEFINE(M_NEWNFSLAYOUT, "NFSCL layout", "NFSv4.1 Layout"); 132 MALLOC_DEFINE(M_NEWNFSFLAYOUT, "NFSCL flayout", "NFSv4.1 File Layout"); 133 MALLOC_DEFINE(M_NEWNFSDEVINFO, "NFSCL devinfo", "NFSv4.1 Device Info"); 134 MALLOC_DEFINE(M_NEWNFSSOCKREQ, "NFSCL sockreq", "NFS Sock Req"); 135 MALLOC_DEFINE(M_NEWNFSCLDS, "NFSCL session", "NFSv4.1 Session"); 136 MALLOC_DEFINE(M_NEWNFSLAYRECALL, "NFSCL layrecall", "NFSv4.1 Layout Recall"); 137 MALLOC_DEFINE(M_NEWNFSDSESSION, "NFSD session", "NFSD Session for a client"); 138 139 /* 140 * Definition of mutex locks. 141 * newnfsd_mtx is used in nfsrvd_nfsd() to protect the nfs socket list 142 * and assorted other nfsd structures. 143 */ 144 struct mtx newnfsd_mtx; 145 struct mtx nfs_sockl_mutex; 146 struct mtx nfs_state_mutex; 147 struct mtx nfs_nameid_mutex; 148 struct mtx nfs_req_mutex; 149 struct mtx nfs_slock_mutex; 150 struct mtx nfs_clstate_mutex; 151 152 /* local functions */ 153 static int nfssvc_call(struct thread *, struct nfssvc_args *, struct ucred *); 154 155 #ifdef __NO_STRICT_ALIGNMENT 156 /* 157 * These architectures don't need re-alignment, so just return. 158 */ 159 int 160 newnfs_realign(struct mbuf **pm, int how) 161 { 162 163 return (0); 164 } 165 #else /* !__NO_STRICT_ALIGNMENT */ 166 /* 167 * newnfs_realign: 168 * 169 * Check for badly aligned mbuf data and realign by copying the unaligned 170 * portion of the data into a new mbuf chain and freeing the portions 171 * of the old chain that were replaced. 172 * 173 * We cannot simply realign the data within the existing mbuf chain 174 * because the underlying buffers may contain other rpc commands and 175 * we cannot afford to overwrite them. 176 * 177 * We would prefer to avoid this situation entirely. The situation does 178 * not occur with NFS/UDP and is supposed to only occasionally occur 179 * with TCP. Use vfs.nfs.realign_count and realign_test to check this. 180 * 181 */ 182 int 183 newnfs_realign(struct mbuf **pm, int how) 184 { 185 struct mbuf *m, *n; 186 int off, space; 187 188 ++nfs_realign_test; 189 while ((m = *pm) != NULL) { 190 if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) { 191 /* 192 * NB: we can't depend on m_pkthdr.len to help us 193 * decide what to do here. May not be worth doing 194 * the m_length calculation as m_copyback will 195 * expand the mbuf chain below as needed. 196 */ 197 space = m_length(m, NULL); 198 if (space >= MINCLSIZE) { 199 /* NB: m_copyback handles space > MCLBYTES */ 200 n = m_getcl(how, MT_DATA, 0); 201 } else 202 n = m_get(how, MT_DATA); 203 if (n == NULL) 204 return (ENOMEM); 205 /* 206 * Align the remainder of the mbuf chain. 207 */ 208 n->m_len = 0; 209 off = 0; 210 while (m != NULL) { 211 m_copyback(n, off, m->m_len, mtod(m, caddr_t)); 212 off += m->m_len; 213 m = m->m_next; 214 } 215 m_freem(*pm); 216 *pm = n; 217 ++nfs_realign_count; 218 break; 219 } 220 pm = &m->m_next; 221 } 222 223 return (0); 224 } 225 #endif /* __NO_STRICT_ALIGNMENT */ 226 227 #ifdef notdef 228 static void 229 nfsrv_object_create(struct vnode *vp, struct thread *td) 230 { 231 232 if (vp == NULL || vp->v_type != VREG) 233 return; 234 (void) vfs_object_create(vp, td, td->td_ucred); 235 } 236 #endif 237 238 /* 239 * Look up a file name. Basically just initialize stuff and call namei(). 240 */ 241 int 242 nfsrv_lookupfilename(struct nameidata *ndp, char *fname, NFSPROC_T *p __unused) 243 { 244 int error; 245 246 NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, fname); 247 error = namei(ndp); 248 if (!error) { 249 NDFREE_PNBUF(ndp); 250 } 251 return (error); 252 } 253 254 /* 255 * Copy NFS uid, gids to the cred structure. 256 */ 257 void 258 newnfs_copycred(struct nfscred *nfscr, struct ucred *cr) 259 { 260 261 KASSERT(nfscr->nfsc_ngroups >= 0, 262 ("newnfs_copycred: negative nfsc_ngroups")); 263 cr->cr_uid = nfscr->nfsc_uid; 264 crsetgroups(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups); 265 } 266 267 /* 268 * Map args from nfsmsleep() to msleep(). 269 */ 270 int 271 nfsmsleep(void *chan, void *mutex, int prio, const char *wmesg, 272 struct timespec *ts) 273 { 274 u_int64_t nsecval; 275 int error, timeo; 276 277 if (ts) { 278 timeo = hz * ts->tv_sec; 279 nsecval = (u_int64_t)ts->tv_nsec; 280 nsecval = ((nsecval * ((u_int64_t)hz)) + 500000000) / 281 1000000000; 282 timeo += (int)nsecval; 283 } else { 284 timeo = 0; 285 } 286 error = msleep(chan, (struct mtx *)mutex, prio, wmesg, timeo); 287 return (error); 288 } 289 290 /* 291 * Get the file system info for the server. For now, just assume FFS. 292 */ 293 void 294 nfsvno_getfs(struct nfsfsinfo *sip, int isdgram) 295 { 296 int pref; 297 298 /* 299 * XXX 300 * There should be file system VFS OP(s) to get this information. 301 * For now, assume ufs. 302 */ 303 if (isdgram) 304 pref = NFS_MAXDGRAMDATA; 305 else 306 pref = nfs_srvmaxio; 307 sip->fs_rtmax = nfs_srvmaxio; 308 sip->fs_rtpref = pref; 309 sip->fs_rtmult = NFS_FABLKSIZE; 310 sip->fs_wtmax = nfs_srvmaxio; 311 sip->fs_wtpref = pref; 312 sip->fs_wtmult = NFS_FABLKSIZE; 313 sip->fs_dtpref = pref; 314 sip->fs_maxfilesize = 0xffffffffffffffffull; 315 sip->fs_timedelta.tv_sec = 0; 316 sip->fs_timedelta.tv_nsec = 1; 317 sip->fs_properties = (NFSV3FSINFO_LINK | 318 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 319 NFSV3FSINFO_CANSETTIME); 320 } 321 322 /* 323 * Do the pathconf vnode op. 324 */ 325 int 326 nfsvno_pathconf(struct vnode *vp, int flag, long *retf, 327 struct ucred *cred, struct thread *p) 328 { 329 int error; 330 331 error = VOP_PATHCONF(vp, flag, retf); 332 if (error == EOPNOTSUPP || error == EINVAL) { 333 /* 334 * Some file systems return EINVAL for name arguments not 335 * supported and some return EOPNOTSUPP for this case. 336 * So the NFSv3 Pathconf RPC doesn't fail for these cases, 337 * just fake them. 338 */ 339 switch (flag) { 340 case _PC_LINK_MAX: 341 *retf = NFS_LINK_MAX; 342 break; 343 case _PC_NAME_MAX: 344 *retf = NAME_MAX; 345 break; 346 case _PC_CHOWN_RESTRICTED: 347 *retf = 1; 348 break; 349 case _PC_NO_TRUNC: 350 *retf = 1; 351 break; 352 default: 353 /* 354 * Only happens if a _PC_xxx is added to the server, 355 * but this isn't updated. 356 */ 357 *retf = 0; 358 printf("nfsrvd pathconf flag=%d not supp\n", flag); 359 } 360 error = 0; 361 } 362 NFSEXITCODE(error); 363 return (error); 364 } 365 366 /* Fake nfsrv_atroot. Just return 0 */ 367 int 368 nfsrv_atroot(struct vnode *vp, uint64_t *retp) 369 { 370 371 return (0); 372 } 373 374 /* 375 * Set the credentials to refer to root. 376 * If only the various BSDen could agree on whether cr_gid is a separate 377 * field or cr_groups[0]... 378 */ 379 void 380 newnfs_setroot(struct ucred *cred) 381 { 382 383 cred->cr_uid = 0; 384 cred->cr_groups[0] = 0; 385 cred->cr_ngroups = 1; 386 } 387 388 /* 389 * Get the client credential. Used for Renew and recovery. 390 */ 391 struct ucred * 392 newnfs_getcred(void) 393 { 394 struct ucred *cred; 395 struct thread *td = curthread; 396 397 cred = crdup(td->td_ucred); 398 newnfs_setroot(cred); 399 return (cred); 400 } 401 402 /* 403 * Sleep for a short period of time unless errval == NFSERR_GRACE, where 404 * the sleep should be for 5 seconds. 405 * Since lbolt doesn't exist in FreeBSD-CURRENT, just use a timeout on 406 * an event that never gets a wakeup. Only return EINTR or 0. 407 */ 408 int 409 nfs_catnap(int prio, int errval, const char *wmesg) 410 { 411 static int non_event; 412 int ret; 413 414 if (errval == NFSERR_GRACE) 415 ret = tsleep(&non_event, prio, wmesg, 5 * hz); 416 else 417 ret = tsleep(&non_event, prio, wmesg, 1); 418 if (ret != EINTR) 419 ret = 0; 420 return (ret); 421 } 422 423 /* 424 * Get referral. For now, just fail. 425 */ 426 struct nfsreferral * 427 nfsv4root_getreferral(struct vnode *vp, struct vnode *dvp, u_int32_t fileno) 428 { 429 430 return (NULL); 431 } 432 433 static int 434 nfssvc_nfscommon(struct thread *td, struct nfssvc_args *uap) 435 { 436 int error; 437 438 NFSD_CURVNET_SET(NFSD_TD_TO_VNET(td)); 439 error = nfssvc_call(td, uap, td->td_ucred); 440 NFSD_CURVNET_RESTORE(); 441 NFSEXITCODE(error); 442 return (error); 443 } 444 445 static int 446 nfssvc_call(struct thread *p, struct nfssvc_args *uap, struct ucred *cred) 447 { 448 int error = EINVAL, i, j; 449 struct nfsd_idargs nid; 450 struct nfsd_oidargs onid; 451 struct { 452 int vers; /* Just the first field of nfsstats. */ 453 } nfsstatver; 454 455 if (uap->flag & NFSSVC_IDNAME) { 456 if ((uap->flag & NFSSVC_NEWSTRUCT) != 0) 457 error = copyin(uap->argp, &nid, sizeof(nid)); 458 else { 459 error = copyin(uap->argp, &onid, sizeof(onid)); 460 if (error == 0) { 461 nid.nid_flag = onid.nid_flag; 462 nid.nid_uid = onid.nid_uid; 463 nid.nid_gid = onid.nid_gid; 464 nid.nid_usermax = onid.nid_usermax; 465 nid.nid_usertimeout = onid.nid_usertimeout; 466 nid.nid_name = onid.nid_name; 467 nid.nid_namelen = onid.nid_namelen; 468 nid.nid_ngroup = 0; 469 nid.nid_grps = NULL; 470 } 471 } 472 if (error) 473 goto out; 474 error = nfssvc_idname(&nid); 475 goto out; 476 } else if (uap->flag & NFSSVC_GETSTATS) { 477 if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) { 478 /* Copy fields to the old ext_nfsstat structure. */ 479 oldnfsstats.attrcache_hits = 480 NFSD_VNET(nfsstatsv1_p)->attrcache_hits; 481 oldnfsstats.attrcache_misses = 482 NFSD_VNET(nfsstatsv1_p)->attrcache_misses; 483 oldnfsstats.lookupcache_hits = 484 NFSD_VNET(nfsstatsv1_p)->lookupcache_hits; 485 oldnfsstats.lookupcache_misses = 486 NFSD_VNET(nfsstatsv1_p)->lookupcache_misses; 487 oldnfsstats.direofcache_hits = 488 NFSD_VNET(nfsstatsv1_p)->direofcache_hits; 489 oldnfsstats.direofcache_misses = 490 NFSD_VNET(nfsstatsv1_p)->direofcache_misses; 491 oldnfsstats.accesscache_hits = 492 NFSD_VNET(nfsstatsv1_p)->accesscache_hits; 493 oldnfsstats.accesscache_misses = 494 NFSD_VNET(nfsstatsv1_p)->accesscache_misses; 495 oldnfsstats.biocache_reads = 496 NFSD_VNET(nfsstatsv1_p)->biocache_reads; 497 oldnfsstats.read_bios = 498 NFSD_VNET(nfsstatsv1_p)->read_bios; 499 oldnfsstats.read_physios = 500 NFSD_VNET(nfsstatsv1_p)->read_physios; 501 oldnfsstats.biocache_writes = 502 NFSD_VNET(nfsstatsv1_p)->biocache_writes; 503 oldnfsstats.write_bios = 504 NFSD_VNET(nfsstatsv1_p)->write_bios; 505 oldnfsstats.write_physios = 506 NFSD_VNET(nfsstatsv1_p)->write_physios; 507 oldnfsstats.biocache_readlinks = 508 NFSD_VNET(nfsstatsv1_p)->biocache_readlinks; 509 oldnfsstats.readlink_bios = 510 NFSD_VNET(nfsstatsv1_p)->readlink_bios; 511 oldnfsstats.biocache_readdirs = 512 NFSD_VNET(nfsstatsv1_p)->biocache_readdirs; 513 oldnfsstats.readdir_bios = 514 NFSD_VNET(nfsstatsv1_p)->readdir_bios; 515 for (i = 0; i < NFSV4_NPROCS; i++) 516 oldnfsstats.rpccnt[i] = 517 NFSD_VNET(nfsstatsv1_p)->rpccnt[i]; 518 oldnfsstats.rpcretries = 519 NFSD_VNET(nfsstatsv1_p)->rpcretries; 520 for (i = 0; i < NFSV4OP_NOPS; i++) 521 oldnfsstats.srvrpccnt[i] = 522 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i]; 523 for (i = NFSV42_NOPS, j = NFSV4OP_NOPS; 524 i < NFSV42_NOPS + NFSV4OP_FAKENOPS; i++, j++) 525 oldnfsstats.srvrpccnt[j] = 526 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i]; 527 oldnfsstats.reserved_0 = 0; 528 oldnfsstats.reserved_1 = 0; 529 oldnfsstats.rpcrequests = 530 NFSD_VNET(nfsstatsv1_p)->rpcrequests; 531 oldnfsstats.rpctimeouts = 532 NFSD_VNET(nfsstatsv1_p)->rpctimeouts; 533 oldnfsstats.rpcunexpected = 534 NFSD_VNET(nfsstatsv1_p)->rpcunexpected; 535 oldnfsstats.rpcinvalid = 536 NFSD_VNET(nfsstatsv1_p)->rpcinvalid; 537 oldnfsstats.srvcache_inproghits = 538 NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits; 539 oldnfsstats.reserved_2 = 0; 540 oldnfsstats.srvcache_nonidemdonehits = 541 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits; 542 oldnfsstats.srvcache_misses = 543 NFSD_VNET(nfsstatsv1_p)->srvcache_misses; 544 oldnfsstats.srvcache_tcppeak = 545 NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak; 546 oldnfsstats.srvcache_size = 547 NFSD_VNET(nfsstatsv1_p)->srvcache_size; 548 oldnfsstats.srvclients = 549 NFSD_VNET(nfsstatsv1_p)->srvclients; 550 oldnfsstats.srvopenowners = 551 NFSD_VNET(nfsstatsv1_p)->srvopenowners; 552 oldnfsstats.srvopens = 553 NFSD_VNET(nfsstatsv1_p)->srvopens; 554 oldnfsstats.srvlockowners = 555 NFSD_VNET(nfsstatsv1_p)->srvlockowners; 556 oldnfsstats.srvlocks = 557 NFSD_VNET(nfsstatsv1_p)->srvlocks; 558 oldnfsstats.srvdelegates = 559 NFSD_VNET(nfsstatsv1_p)->srvdelegates; 560 for (i = 0; i < NFSV4OP_CBNOPS; i++) 561 oldnfsstats.cbrpccnt[i] = 562 NFSD_VNET(nfsstatsv1_p)->cbrpccnt[i]; 563 oldnfsstats.clopenowners = 564 NFSD_VNET(nfsstatsv1_p)->clopenowners; 565 oldnfsstats.clopens = NFSD_VNET(nfsstatsv1_p)->clopens; 566 oldnfsstats.cllockowners = 567 NFSD_VNET(nfsstatsv1_p)->cllockowners; 568 oldnfsstats.cllocks = NFSD_VNET(nfsstatsv1_p)->cllocks; 569 oldnfsstats.cldelegates = 570 NFSD_VNET(nfsstatsv1_p)->cldelegates; 571 oldnfsstats.cllocalopenowners = 572 NFSD_VNET(nfsstatsv1_p)->cllocalopenowners; 573 oldnfsstats.cllocalopens = 574 NFSD_VNET(nfsstatsv1_p)->cllocalopens; 575 oldnfsstats.cllocallockowners = 576 NFSD_VNET(nfsstatsv1_p)->cllocallockowners; 577 oldnfsstats.cllocallocks = 578 NFSD_VNET(nfsstatsv1_p)->cllocallocks; 579 error = copyout(&oldnfsstats, uap->argp, 580 sizeof (oldnfsstats)); 581 } else { 582 error = copyin(uap->argp, &nfsstatver, 583 sizeof(nfsstatver)); 584 if (error == 0) { 585 if (nfsstatver.vers == NFSSTATS_OV1) { 586 /* Copy nfsstatsv1 to nfsstatsov1. */ 587 nfsstatsov1.attrcache_hits = 588 NFSD_VNET(nfsstatsv1_p)->attrcache_hits; 589 nfsstatsov1.attrcache_misses = 590 NFSD_VNET(nfsstatsv1_p)->attrcache_misses; 591 nfsstatsov1.lookupcache_hits = 592 NFSD_VNET(nfsstatsv1_p)->lookupcache_hits; 593 nfsstatsov1.lookupcache_misses = 594 NFSD_VNET(nfsstatsv1_p)->lookupcache_misses; 595 nfsstatsov1.direofcache_hits = 596 NFSD_VNET(nfsstatsv1_p)->direofcache_hits; 597 nfsstatsov1.direofcache_misses = 598 NFSD_VNET(nfsstatsv1_p)->direofcache_misses; 599 nfsstatsov1.accesscache_hits = 600 NFSD_VNET(nfsstatsv1_p)->accesscache_hits; 601 nfsstatsov1.accesscache_misses = 602 NFSD_VNET(nfsstatsv1_p)->accesscache_misses; 603 nfsstatsov1.biocache_reads = 604 NFSD_VNET(nfsstatsv1_p)->biocache_reads; 605 nfsstatsov1.read_bios = 606 NFSD_VNET(nfsstatsv1_p)->read_bios; 607 nfsstatsov1.read_physios = 608 NFSD_VNET(nfsstatsv1_p)->read_physios; 609 nfsstatsov1.biocache_writes = 610 NFSD_VNET(nfsstatsv1_p)->biocache_writes; 611 nfsstatsov1.write_bios = 612 NFSD_VNET(nfsstatsv1_p)->write_bios; 613 nfsstatsov1.write_physios = 614 NFSD_VNET(nfsstatsv1_p)->write_physios; 615 nfsstatsov1.biocache_readlinks = 616 NFSD_VNET(nfsstatsv1_p)->biocache_readlinks; 617 nfsstatsov1.readlink_bios = 618 NFSD_VNET(nfsstatsv1_p)->readlink_bios; 619 nfsstatsov1.biocache_readdirs = 620 NFSD_VNET(nfsstatsv1_p)->biocache_readdirs; 621 nfsstatsov1.readdir_bios = 622 NFSD_VNET(nfsstatsv1_p)->readdir_bios; 623 for (i = 0; i < NFSV42_OLDNPROCS; i++) 624 nfsstatsov1.rpccnt[i] = 625 NFSD_VNET(nfsstatsv1_p)->rpccnt[i]; 626 nfsstatsov1.rpcretries = 627 NFSD_VNET(nfsstatsv1_p)->rpcretries; 628 for (i = 0; i < NFSV42_PURENOPS; i++) 629 nfsstatsov1.srvrpccnt[i] = 630 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i]; 631 for (i = NFSV42_NOPS, 632 j = NFSV42_PURENOPS; 633 i < NFSV42_NOPS + NFSV4OP_FAKENOPS; 634 i++, j++) 635 nfsstatsov1.srvrpccnt[j] = 636 NFSD_VNET(nfsstatsv1_p)->srvrpccnt[i]; 637 nfsstatsov1.reserved_0 = 0; 638 nfsstatsov1.reserved_1 = 0; 639 nfsstatsov1.rpcrequests = 640 NFSD_VNET(nfsstatsv1_p)->rpcrequests; 641 nfsstatsov1.rpctimeouts = 642 NFSD_VNET(nfsstatsv1_p)->rpctimeouts; 643 nfsstatsov1.rpcunexpected = 644 NFSD_VNET(nfsstatsv1_p)->rpcunexpected; 645 nfsstatsov1.rpcinvalid = 646 NFSD_VNET(nfsstatsv1_p)->rpcinvalid; 647 nfsstatsov1.srvcache_inproghits = 648 NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits; 649 nfsstatsov1.reserved_2 = 0; 650 nfsstatsov1.srvcache_nonidemdonehits = 651 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits; 652 nfsstatsov1.srvcache_misses = 653 NFSD_VNET(nfsstatsv1_p)->srvcache_misses; 654 nfsstatsov1.srvcache_tcppeak = 655 NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak; 656 nfsstatsov1.srvcache_size = 657 NFSD_VNET(nfsstatsv1_p)->srvcache_size; 658 nfsstatsov1.srvclients = 659 NFSD_VNET(nfsstatsv1_p)->srvclients; 660 nfsstatsov1.srvopenowners = 661 NFSD_VNET(nfsstatsv1_p)->srvopenowners; 662 nfsstatsov1.srvopens = 663 NFSD_VNET(nfsstatsv1_p)->srvopens; 664 nfsstatsov1.srvlockowners = 665 NFSD_VNET(nfsstatsv1_p)->srvlockowners; 666 nfsstatsov1.srvlocks = 667 NFSD_VNET(nfsstatsv1_p)->srvlocks; 668 nfsstatsov1.srvdelegates = 669 NFSD_VNET(nfsstatsv1_p)->srvdelegates; 670 for (i = 0; i < NFSV42_CBNOPS; i++) 671 nfsstatsov1.cbrpccnt[i] = 672 NFSD_VNET(nfsstatsv1_p)->cbrpccnt[i]; 673 nfsstatsov1.clopenowners = 674 NFSD_VNET(nfsstatsv1_p)->clopenowners; 675 nfsstatsov1.clopens = 676 NFSD_VNET(nfsstatsv1_p)->clopens; 677 nfsstatsov1.cllockowners = 678 NFSD_VNET(nfsstatsv1_p)->cllockowners; 679 nfsstatsov1.cllocks = 680 NFSD_VNET(nfsstatsv1_p)->cllocks; 681 nfsstatsov1.cldelegates = 682 NFSD_VNET(nfsstatsv1_p)->cldelegates; 683 nfsstatsov1.cllocalopenowners = 684 NFSD_VNET(nfsstatsv1_p)->cllocalopenowners; 685 nfsstatsov1.cllocalopens = 686 NFSD_VNET(nfsstatsv1_p)->cllocalopens; 687 nfsstatsov1.cllocallockowners = 688 NFSD_VNET(nfsstatsv1_p)->cllocallockowners; 689 nfsstatsov1.cllocallocks = 690 NFSD_VNET(nfsstatsv1_p)->cllocallocks; 691 nfsstatsov1.srvstartcnt = 692 NFSD_VNET(nfsstatsv1_p)->srvstartcnt; 693 nfsstatsov1.srvdonecnt = 694 NFSD_VNET(nfsstatsv1_p)->srvdonecnt; 695 for (i = NFSV42_NOPS, 696 j = NFSV42_PURENOPS; 697 i < NFSV42_NOPS + NFSV4OP_FAKENOPS; 698 i++, j++) { 699 nfsstatsov1.srvbytes[j] = 700 NFSD_VNET(nfsstatsv1_p)->srvbytes[i]; 701 nfsstatsov1.srvops[j] = 702 NFSD_VNET(nfsstatsv1_p)->srvops[i]; 703 nfsstatsov1.srvduration[j] = 704 NFSD_VNET(nfsstatsv1_p)->srvduration[i]; 705 } 706 nfsstatsov1.busyfrom = 707 NFSD_VNET(nfsstatsv1_p)->busyfrom; 708 nfsstatsov1.busyfrom = 709 NFSD_VNET(nfsstatsv1_p)->busyfrom; 710 error = copyout(&nfsstatsov1, uap->argp, 711 sizeof(nfsstatsov1)); 712 } else if (nfsstatver.vers != NFSSTATS_V1) 713 error = EPERM; 714 else 715 error = copyout(NFSD_VNET(nfsstatsv1_p), 716 uap->argp, sizeof(nfsstatsv1)); 717 } 718 } 719 if (error == 0) { 720 if ((uap->flag & NFSSVC_ZEROCLTSTATS) != 0) { 721 NFSD_VNET(nfsstatsv1_p)->attrcache_hits = 0; 722 NFSD_VNET(nfsstatsv1_p)->attrcache_misses = 0; 723 NFSD_VNET(nfsstatsv1_p)->lookupcache_hits = 0; 724 NFSD_VNET(nfsstatsv1_p)->lookupcache_misses = 0; 725 NFSD_VNET(nfsstatsv1_p)->direofcache_hits = 0; 726 NFSD_VNET(nfsstatsv1_p)->direofcache_misses = 0; 727 NFSD_VNET(nfsstatsv1_p)->accesscache_hits = 0; 728 NFSD_VNET(nfsstatsv1_p)->accesscache_misses = 0; 729 NFSD_VNET(nfsstatsv1_p)->biocache_reads = 0; 730 NFSD_VNET(nfsstatsv1_p)->read_bios = 0; 731 NFSD_VNET(nfsstatsv1_p)->read_physios = 0; 732 NFSD_VNET(nfsstatsv1_p)->biocache_writes = 0; 733 NFSD_VNET(nfsstatsv1_p)->write_bios = 0; 734 NFSD_VNET(nfsstatsv1_p)->write_physios = 0; 735 NFSD_VNET(nfsstatsv1_p)->biocache_readlinks = 0; 736 NFSD_VNET(nfsstatsv1_p)->readlink_bios = 0; 737 NFSD_VNET(nfsstatsv1_p)->biocache_readdirs = 0; 738 NFSD_VNET(nfsstatsv1_p)->readdir_bios = 0; 739 NFSD_VNET(nfsstatsv1_p)->rpcretries = 0; 740 NFSD_VNET(nfsstatsv1_p)->rpcrequests = 0; 741 NFSD_VNET(nfsstatsv1_p)->rpctimeouts = 0; 742 NFSD_VNET(nfsstatsv1_p)->rpcunexpected = 0; 743 NFSD_VNET(nfsstatsv1_p)->rpcinvalid = 0; 744 bzero(NFSD_VNET(nfsstatsv1_p)->rpccnt, 745 sizeof(NFSD_VNET(nfsstatsv1_p)->rpccnt)); 746 } 747 if ((uap->flag & NFSSVC_ZEROSRVSTATS) != 0) { 748 NFSD_VNET(nfsstatsv1_p)->srvcache_inproghits = 0; 749 NFSD_VNET(nfsstatsv1_p)->srvcache_nonidemdonehits = 0; 750 NFSD_VNET(nfsstatsv1_p)->srvcache_misses = 0; 751 NFSD_VNET(nfsstatsv1_p)->srvcache_tcppeak = 0; 752 bzero(NFSD_VNET(nfsstatsv1_p)->srvrpccnt, 753 sizeof(NFSD_VNET(nfsstatsv1_p)->srvrpccnt)); 754 bzero(NFSD_VNET(nfsstatsv1_p)->cbrpccnt, 755 sizeof(NFSD_VNET(nfsstatsv1_p)->cbrpccnt)); 756 } 757 } 758 goto out; 759 } else if (uap->flag & NFSSVC_NFSUSERDPORT) { 760 u_short sockport; 761 struct nfsuserd_args nargs; 762 763 if ((uap->flag & NFSSVC_NEWSTRUCT) == 0) { 764 error = copyin(uap->argp, (caddr_t)&sockport, 765 sizeof (u_short)); 766 if (error == 0) { 767 nargs.nuserd_family = AF_INET; 768 nargs.nuserd_port = sockport; 769 } 770 } else { 771 /* 772 * New nfsuserd_args structure, which indicates 773 * which IP version to use along with the port#. 774 */ 775 error = copyin(uap->argp, &nargs, sizeof(nargs)); 776 } 777 if (!error) 778 error = nfsrv_nfsuserdport(&nargs, p); 779 } else if (uap->flag & NFSSVC_NFSUSERDDELPORT) { 780 nfsrv_nfsuserddelport(); 781 error = 0; 782 } 783 784 out: 785 NFSEXITCODE(error); 786 return (error); 787 } 788 789 /* 790 * called by all three modevent routines, so that it gets things 791 * initialized soon enough. 792 */ 793 void 794 newnfs_portinit(void) 795 { 796 static int inited = 0; 797 798 if (inited) 799 return; 800 inited = 1; 801 /* Initialize SMP locks used by both client and server. */ 802 mtx_init(&newnfsd_mtx, "newnfsd_mtx", NULL, MTX_DEF); 803 mtx_init(&nfs_state_mutex, "nfs_state_mutex", NULL, MTX_DEF); 804 mtx_init(&nfs_clstate_mutex, "nfs_clstate_mutex", NULL, MTX_DEF); 805 } 806 807 /* 808 * Determine if the file system supports NFSv4 ACLs. 809 * Return 1 if it does, 0 otherwise. 810 */ 811 int 812 nfs_supportsnfsv4acls(struct vnode *vp) 813 { 814 int error; 815 long retval; 816 817 ASSERT_VOP_LOCKED(vp, "nfs supports nfsv4acls"); 818 819 if (nfsrv_useacl == 0) 820 return (0); 821 error = VOP_PATHCONF(vp, _PC_ACL_NFS4, &retval); 822 if (error == 0 && retval != 0) 823 return (1); 824 return (0); 825 } 826 827 /* 828 * These are the first fields of all the context structures passed into 829 * nfs_pnfsio(). 830 */ 831 struct pnfsio { 832 int done; 833 int inprog; 834 struct task tsk; 835 }; 836 837 /* 838 * Do a mirror I/O on a pNFS thread. 839 */ 840 int 841 nfs_pnfsio(task_fn_t *func, void *context) 842 { 843 struct pnfsio *pio; 844 int ret; 845 static struct taskqueue *pnfsioq = NULL; 846 847 pio = (struct pnfsio *)context; 848 if (pnfsioq == NULL) { 849 if (nfs_pnfsiothreads == 0) 850 return (EPERM); 851 if (nfs_pnfsiothreads < 0) 852 nfs_pnfsiothreads = mp_ncpus * 4; 853 pnfsioq = taskqueue_create("pnfsioq", M_WAITOK, 854 taskqueue_thread_enqueue, &pnfsioq); 855 if (pnfsioq == NULL) 856 return (ENOMEM); 857 ret = taskqueue_start_threads(&pnfsioq, nfs_pnfsiothreads, 858 0, "pnfsiot"); 859 if (ret != 0) { 860 taskqueue_free(pnfsioq); 861 pnfsioq = NULL; 862 return (ret); 863 } 864 } 865 pio->inprog = 1; 866 TASK_INIT(&pio->tsk, 0, func, context); 867 ret = taskqueue_enqueue(pnfsioq, &pio->tsk); 868 if (ret != 0) 869 pio->inprog = 0; 870 return (ret); 871 } 872 873 /* 874 * Initialize everything that needs to be initialized for a vnet. 875 */ 876 static void 877 nfs_vnetinit(const void *unused __unused) 878 { 879 880 if (IS_DEFAULT_VNET(curvnet)) 881 NFSD_VNET(nfsstatsv1_p) = &nfsstatsv1; 882 else 883 NFSD_VNET(nfsstatsv1_p) = malloc(sizeof(struct nfsstatsv1), 884 M_TEMP, M_WAITOK | M_ZERO); 885 mtx_init(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx, "nfsuserd", 886 NULL, MTX_DEF); 887 } 888 VNET_SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_FIRST, 889 nfs_vnetinit, NULL); 890 891 static void 892 nfs_cleanup(void *unused __unused) 893 { 894 895 mtx_destroy(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx); 896 if (!IS_DEFAULT_VNET(curvnet)) { 897 free(NFSD_VNET(nfsstatsv1_p), M_TEMP); 898 NFSD_VNET(nfsstatsv1_p) = NULL; 899 } 900 /* Clean out the name<-->id cache. */ 901 nfsrv_cleanusergroup(); 902 } 903 VNET_SYSUNINIT(nfs_cleanup, SI_SUB_VNET_DONE, SI_ORDER_FIRST, 904 nfs_cleanup, NULL); 905 906 extern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *); 907 908 /* 909 * Called once to initialize data structures... 910 */ 911 static int 912 nfscommon_modevent(module_t mod, int type, void *data) 913 { 914 int error = 0; 915 static int loaded = 0; 916 917 switch (type) { 918 case MOD_LOAD: 919 if (loaded) 920 goto out; 921 newnfs_portinit(); 922 mtx_init(&nfs_nameid_mutex, "nfs_nameid_mutex", NULL, MTX_DEF); 923 mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF); 924 mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF); 925 mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF); 926 mtx_init(&nfsrv_dslock_mtx, "nfs4ds", NULL, MTX_DEF); 927 TAILQ_INIT(&nfsrv_devidhead); 928 newnfs_init(); 929 nfsd_call_nfscommon = nfssvc_nfscommon; 930 loaded = 1; 931 break; 932 933 case MOD_UNLOAD: 934 if (newnfs_numnfsd != 0 || 935 NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING || 936 nfs_numnfscbd != 0) { 937 error = EBUSY; 938 break; 939 } 940 941 nfsd_call_nfscommon = NULL; 942 /* and get rid of the mutexes */ 943 mtx_destroy(&nfs_nameid_mutex); 944 mtx_destroy(&newnfsd_mtx); 945 mtx_destroy(&nfs_state_mutex); 946 mtx_destroy(&nfs_clstate_mutex); 947 mtx_destroy(&nfs_sockl_mutex); 948 mtx_destroy(&nfs_slock_mutex); 949 mtx_destroy(&nfs_req_mutex); 950 mtx_destroy(&nfsrv_dslock_mtx); 951 loaded = 0; 952 break; 953 default: 954 error = EOPNOTSUPP; 955 break; 956 } 957 958 out: 959 NFSEXITCODE(error); 960 return error; 961 } 962 static moduledata_t nfscommon_mod = { 963 "nfscommon", 964 nfscommon_modevent, 965 NULL, 966 }; 967 DECLARE_MODULE(nfscommon, nfscommon_mod, SI_SUB_VFS, SI_ORDER_ANY); 968 969 /* So that loader and kldload(2) can find us, wherever we are.. */ 970 MODULE_VERSION(nfscommon, 1); 971 MODULE_DEPEND(nfscommon, nfssvc, 1, 1, 1); 972 MODULE_DEPEND(nfscommon, krpc, 1, 1, 1); 973