1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1989, 1993, 1995 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 * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "opt_bootp.h" 41 #include "opt_nfsroot.h" 42 #include "opt_kern_tls.h" 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/bio.h> 48 #include <sys/buf.h> 49 #include <sys/clock.h> 50 #include <sys/jail.h> 51 #include <sys/limits.h> 52 #include <sys/lock.h> 53 #include <sys/malloc.h> 54 #include <sys/mbuf.h> 55 #include <sys/mount.h> 56 #include <sys/proc.h> 57 #include <sys/socket.h> 58 #include <sys/socketvar.h> 59 #include <sys/sockio.h> 60 #include <sys/sysctl.h> 61 #include <sys/vnode.h> 62 #include <sys/signalvar.h> 63 64 #include <vm/vm.h> 65 #include <vm/vm_extern.h> 66 #include <vm/uma.h> 67 68 #include <net/if.h> 69 #include <net/route.h> 70 #include <net/route/route_ctl.h> 71 #include <netinet/in.h> 72 73 #include <fs/nfs/nfsport.h> 74 #include <fs/nfsclient/nfsnode.h> 75 #include <fs/nfsclient/nfsmount.h> 76 #include <fs/nfsclient/nfs.h> 77 #include <nfs/nfsdiskless.h> 78 79 #include <rpc/rpcsec_tls.h> 80 81 FEATURE(nfscl, "NFSv4 client"); 82 83 extern int nfscl_ticks; 84 extern struct timeval nfsboottime; 85 extern int nfsrv_useacl; 86 extern int nfscl_debuglevel; 87 extern enum nfsiod_state ncl_iodwant[NFS_MAXASYNCDAEMON]; 88 extern struct nfsmount *ncl_iodmount[NFS_MAXASYNCDAEMON]; 89 extern struct mtx ncl_iod_mutex; 90 NFSCLSTATEMUTEX; 91 extern struct mtx nfsrv_dslock_mtx; 92 93 MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "NFS request header"); 94 MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "NFS mount struct"); 95 96 SYSCTL_DECL(_vfs_nfs); 97 static int nfs_ip_paranoia = 1; 98 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW, 99 &nfs_ip_paranoia, 0, ""); 100 static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY; 101 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY, 102 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, ""); 103 /* how long between console messages "nfs server foo not responding" */ 104 static int nfs_tprintf_delay = NFS_TPRINTF_DELAY; 105 SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY, 106 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, ""); 107 #ifdef NFS_DEBUG 108 int nfs_debug; 109 SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, 110 "Toggle debug flag"); 111 #endif 112 113 static int nfs_mountroot(struct mount *); 114 static void nfs_sec_name(char *, int *); 115 static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, 116 struct nfs_args *argp, const char *, struct ucred *, 117 struct thread *); 118 static int mountnfs(struct nfs_args *, struct mount *, 119 struct sockaddr *, char *, u_char *, int, u_char *, int, 120 u_char *, int, struct vnode **, struct ucred *, 121 struct thread *, int, int, int, uint32_t, char *, int); 122 static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *, 123 struct sockaddr_storage *, int *, off_t *, 124 struct timeval *); 125 static vfs_mount_t nfs_mount; 126 static vfs_cmount_t nfs_cmount; 127 static vfs_unmount_t nfs_unmount; 128 static vfs_root_t nfs_root; 129 static vfs_statfs_t nfs_statfs; 130 static vfs_sync_t nfs_sync; 131 static vfs_sysctl_t nfs_sysctl; 132 static vfs_purge_t nfs_purge; 133 134 /* 135 * nfs vfs operations. 136 */ 137 static struct vfsops nfs_vfsops = { 138 .vfs_init = ncl_init, 139 .vfs_mount = nfs_mount, 140 .vfs_cmount = nfs_cmount, 141 .vfs_root = vfs_cache_root, 142 .vfs_cachedroot = nfs_root, 143 .vfs_statfs = nfs_statfs, 144 .vfs_sync = nfs_sync, 145 .vfs_uninit = ncl_uninit, 146 .vfs_unmount = nfs_unmount, 147 .vfs_sysctl = nfs_sysctl, 148 .vfs_purge = nfs_purge, 149 }; 150 /* 151 * This macro declares that the file system type is named "nfs". 152 * It also declares a module name of "nfs" and uses vfs_modevent() 153 * as the event handling function. 154 * The main module declaration is found in sys/fs/nfsclient/nfs_clport.c 155 * for "nfscl" and is needed so that a custom event handling 156 * function gets called. MODULE_DEPEND() macros are found there. 157 */ 158 VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK | VFCF_SBDRY); 159 160 MODULE_VERSION(nfs, 1); 161 162 /* 163 * This structure is now defined in sys/nfs/nfs_diskless.c so that it 164 * can be shared by both NFS clients. It is declared here so that it 165 * will be defined for kernels built without NFS_ROOT, although it 166 * isn't used in that case. 167 */ 168 #if !defined(NFS_ROOT) 169 struct nfs_diskless nfs_diskless = { { { 0 } } }; 170 struct nfsv3_diskless nfsv3_diskless = { { { 0 } } }; 171 int nfs_diskless_valid = 0; 172 #endif 173 174 SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 175 &nfs_diskless_valid, 0, 176 "Has the diskless struct been filled correctly"); 177 178 SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, 179 nfsv3_diskless.root_hostnam, 0, "Path to nfs root"); 180 181 SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, 182 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr), 183 "%Ssockaddr_in", "Diskless root nfs address"); 184 185 void newnfsargs_ntoh(struct nfs_args *); 186 static int nfs_mountdiskless(char *, 187 struct sockaddr_in *, struct nfs_args *, 188 struct thread *, struct vnode **, struct mount *); 189 static void nfs_convert_diskless(void); 190 static void nfs_convert_oargs(struct nfs_args *args, 191 struct onfs_args *oargs); 192 193 int 194 newnfs_iosize(struct nfsmount *nmp) 195 { 196 int iosize, maxio; 197 198 /* First, set the upper limit for iosize */ 199 if (nmp->nm_flag & NFSMNT_NFSV4) { 200 maxio = NFS_MAXBSIZE; 201 } else if (nmp->nm_flag & NFSMNT_NFSV3) { 202 if (nmp->nm_sotype == SOCK_DGRAM) 203 maxio = NFS_MAXDGRAMDATA; 204 else 205 maxio = NFS_MAXBSIZE; 206 } else { 207 maxio = NFS_V2MAXDATA; 208 } 209 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0) 210 nmp->nm_rsize = maxio; 211 if (nmp->nm_rsize > NFS_MAXBSIZE) 212 nmp->nm_rsize = NFS_MAXBSIZE; 213 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0) 214 nmp->nm_readdirsize = maxio; 215 if (nmp->nm_readdirsize > nmp->nm_rsize) 216 nmp->nm_readdirsize = nmp->nm_rsize; 217 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0) 218 nmp->nm_wsize = maxio; 219 if (nmp->nm_wsize > NFS_MAXBSIZE) 220 nmp->nm_wsize = NFS_MAXBSIZE; 221 222 /* 223 * Calculate the size used for io buffers. Use the larger 224 * of the two sizes to minimise nfs requests but make sure 225 * that it is at least one VM page to avoid wasting buffer 226 * space. It must also be at least NFS_DIRBLKSIZ, since 227 * that is the buffer size used for directories. 228 */ 229 iosize = imax(nmp->nm_rsize, nmp->nm_wsize); 230 iosize = imax(iosize, PAGE_SIZE); 231 iosize = imax(iosize, NFS_DIRBLKSIZ); 232 nmp->nm_mountp->mnt_stat.f_iosize = iosize; 233 return (iosize); 234 } 235 236 static void 237 nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs) 238 { 239 240 args->version = NFS_ARGSVERSION; 241 args->addr = oargs->addr; 242 args->addrlen = oargs->addrlen; 243 args->sotype = oargs->sotype; 244 args->proto = oargs->proto; 245 args->fh = oargs->fh; 246 args->fhsize = oargs->fhsize; 247 args->flags = oargs->flags; 248 args->wsize = oargs->wsize; 249 args->rsize = oargs->rsize; 250 args->readdirsize = oargs->readdirsize; 251 args->timeo = oargs->timeo; 252 args->retrans = oargs->retrans; 253 args->readahead = oargs->readahead; 254 args->hostname = oargs->hostname; 255 } 256 257 static void 258 nfs_convert_diskless(void) 259 { 260 261 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, 262 sizeof(struct ifaliasreq)); 263 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway, 264 sizeof(struct sockaddr_in)); 265 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args); 266 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) { 267 nfsv3_diskless.root_fhsize = NFSX_MYFH; 268 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH); 269 } else { 270 nfsv3_diskless.root_fhsize = NFSX_V2FH; 271 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH); 272 } 273 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, 274 sizeof(struct sockaddr_in)); 275 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN); 276 nfsv3_diskless.root_time = nfs_diskless.root_time; 277 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam, 278 MAXHOSTNAMELEN); 279 nfs_diskless_valid = 3; 280 } 281 282 /* 283 * nfs statfs call 284 */ 285 static int 286 nfs_statfs(struct mount *mp, struct statfs *sbp) 287 { 288 struct vnode *vp; 289 struct thread *td; 290 struct nfsmount *nmp = VFSTONFS(mp); 291 struct nfsvattr nfsva; 292 struct nfsfsinfo fs; 293 struct nfsstatfs sb; 294 int error = 0, attrflag, gotfsinfo = 0, ret; 295 struct nfsnode *np; 296 297 td = curthread; 298 299 error = vfs_busy(mp, MBF_NOWAIT); 300 if (error) 301 return (error); 302 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE); 303 if (error) { 304 vfs_unbusy(mp); 305 return (error); 306 } 307 vp = NFSTOV(np); 308 mtx_lock(&nmp->nm_mtx); 309 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) { 310 mtx_unlock(&nmp->nm_mtx); 311 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva, 312 &attrflag, NULL); 313 if (!error) 314 gotfsinfo = 1; 315 } else 316 mtx_unlock(&nmp->nm_mtx); 317 if (!error) 318 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva, 319 &attrflag, NULL); 320 if (error != 0) 321 NFSCL_DEBUG(2, "statfs=%d\n", error); 322 if (attrflag == 0) { 323 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1, 324 td->td_ucred, td, &nfsva, NULL, NULL); 325 if (ret) { 326 /* 327 * Just set default values to get things going. 328 */ 329 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr)); 330 nfsva.na_vattr.va_type = VDIR; 331 nfsva.na_vattr.va_mode = 0777; 332 nfsva.na_vattr.va_nlink = 100; 333 nfsva.na_vattr.va_uid = (uid_t)0; 334 nfsva.na_vattr.va_gid = (gid_t)0; 335 nfsva.na_vattr.va_fileid = 2; 336 nfsva.na_vattr.va_gen = 1; 337 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE; 338 nfsva.na_vattr.va_size = 512 * 1024; 339 } 340 } 341 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 342 if (!error) { 343 mtx_lock(&nmp->nm_mtx); 344 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4)) 345 nfscl_loadfsinfo(nmp, &fs); 346 nfscl_loadsbinfo(nmp, &sb, sbp); 347 sbp->f_iosize = newnfs_iosize(nmp); 348 mtx_unlock(&nmp->nm_mtx); 349 if (sbp != &mp->mnt_stat) { 350 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 351 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 352 } 353 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN); 354 } else if (NFS_ISV4(vp)) { 355 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 356 } 357 vput(vp); 358 vfs_unbusy(mp); 359 return (error); 360 } 361 362 /* 363 * nfs version 3 fsinfo rpc call 364 */ 365 int 366 ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred, 367 struct thread *td) 368 { 369 struct nfsfsinfo fs; 370 struct nfsvattr nfsva; 371 int error, attrflag; 372 373 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL); 374 if (!error) { 375 if (attrflag) 376 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 377 1); 378 mtx_lock(&nmp->nm_mtx); 379 nfscl_loadfsinfo(nmp, &fs); 380 mtx_unlock(&nmp->nm_mtx); 381 } 382 return (error); 383 } 384 385 /* 386 * Mount a remote root fs via. nfs. This depends on the info in the 387 * nfs_diskless structure that has been filled in properly by some primary 388 * bootstrap. 389 * It goes something like this: 390 * - do enough of "ifconfig" by calling ifioctl() so that the system 391 * can talk to the server 392 * - If nfs_diskless.mygateway is filled in, use that address as 393 * a default gateway. 394 * - build the rootfs mount point and call mountnfs() to do the rest. 395 * 396 * It is assumed to be safe to read, modify, and write the nfsv3_diskless 397 * structure, as well as other global NFS client variables here, as 398 * nfs_mountroot() will be called once in the boot before any other NFS 399 * client activity occurs. 400 */ 401 static int 402 nfs_mountroot(struct mount *mp) 403 { 404 struct thread *td = curthread; 405 struct nfsv3_diskless *nd = &nfsv3_diskless; 406 struct socket *so; 407 struct vnode *vp; 408 struct ifreq ir; 409 int error; 410 u_long l; 411 char buf[128]; 412 char *cp; 413 414 #if defined(BOOTP_NFSROOT) && defined(BOOTP) 415 bootpc_init(); /* use bootp to get nfs_diskless filled in */ 416 #elif defined(NFS_ROOT) 417 nfs_setup_diskless(); 418 #endif 419 420 if (nfs_diskless_valid == 0) 421 return (-1); 422 if (nfs_diskless_valid == 1) 423 nfs_convert_diskless(); 424 425 /* 426 * Do enough of ifconfig(8) so that the critical net interface can 427 * talk to the server. 428 */ 429 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0, 430 td->td_ucred, td); 431 if (error) 432 panic("nfs_mountroot: socreate(%04x): %d", 433 nd->myif.ifra_addr.sa_family, error); 434 435 #if 0 /* XXX Bad idea */ 436 /* 437 * We might not have been told the right interface, so we pass 438 * over the first ten interfaces of the same kind, until we get 439 * one of them configured. 440 */ 441 442 for (i = strlen(nd->myif.ifra_name) - 1; 443 nd->myif.ifra_name[i] >= '0' && 444 nd->myif.ifra_name[i] <= '9'; 445 nd->myif.ifra_name[i] ++) { 446 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td); 447 if(!error) 448 break; 449 } 450 #endif 451 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td); 452 if (error) 453 panic("nfs_mountroot: SIOCAIFADDR: %d", error); 454 if ((cp = kern_getenv("boot.netif.mtu")) != NULL) { 455 ir.ifr_mtu = strtol(cp, NULL, 10); 456 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ); 457 freeenv(cp); 458 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td); 459 if (error) 460 printf("nfs_mountroot: SIOCSIFMTU: %d", error); 461 } 462 soclose(so); 463 464 /* 465 * If the gateway field is filled in, set it as the default route. 466 * Note that pxeboot will set a default route of 0 if the route 467 * is not set by the DHCP server. Check also for a value of 0 468 * to avoid panicking inappropriately in that situation. 469 */ 470 if (nd->mygateway.sin_len != 0 && 471 nd->mygateway.sin_addr.s_addr != 0) { 472 struct sockaddr_in mask, sin; 473 struct epoch_tracker et; 474 struct rt_addrinfo info; 475 struct rib_cmd_info rc; 476 477 bzero((caddr_t)&mask, sizeof(mask)); 478 sin = mask; 479 sin.sin_family = AF_INET; 480 sin.sin_len = sizeof(sin); 481 /* XXX MRT use table 0 for this sort of thing */ 482 NET_EPOCH_ENTER(et); 483 CURVNET_SET(TD_TO_VNET(td)); 484 485 bzero((caddr_t)&info, sizeof(info)); 486 info.rti_flags = RTF_UP | RTF_GATEWAY; 487 info.rti_info[RTAX_DST] = (struct sockaddr *)&sin; 488 info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&nd->mygateway; 489 info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&mask; 490 491 error = rib_action(RT_DEFAULT_FIB, RTM_ADD, &info, &rc); 492 CURVNET_RESTORE(); 493 NET_EPOCH_EXIT(et); 494 if (error) 495 panic("nfs_mountroot: RTM_ADD: %d", error); 496 } 497 498 /* 499 * Create the rootfs mount point. 500 */ 501 nd->root_args.fh = nd->root_fh; 502 nd->root_args.fhsize = nd->root_fhsize; 503 l = ntohl(nd->root_saddr.sin_addr.s_addr); 504 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s", 505 (l >> 24) & 0xff, (l >> 16) & 0xff, 506 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam); 507 printf("NFS ROOT: %s\n", buf); 508 nd->root_args.hostname = buf; 509 if ((error = nfs_mountdiskless(buf, 510 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) { 511 return (error); 512 } 513 514 /* 515 * This is not really an nfs issue, but it is much easier to 516 * set hostname here and then let the "/etc/rc.xxx" files 517 * mount the right /var based upon its preset value. 518 */ 519 mtx_lock(&prison0.pr_mtx); 520 strlcpy(prison0.pr_hostname, nd->my_hostnam, 521 sizeof(prison0.pr_hostname)); 522 mtx_unlock(&prison0.pr_mtx); 523 inittodr(ntohl(nd->root_time)); 524 return (0); 525 } 526 527 /* 528 * Internal version of mount system call for diskless setup. 529 */ 530 static int 531 nfs_mountdiskless(char *path, 532 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td, 533 struct vnode **vpp, struct mount *mp) 534 { 535 struct sockaddr *nam; 536 int dirlen, error; 537 char *dirpath; 538 539 /* 540 * Find the directory path in "path", which also has the server's 541 * name/ip address in it. 542 */ 543 dirpath = strchr(path, ':'); 544 if (dirpath != NULL) 545 dirlen = strlen(++dirpath); 546 else 547 dirlen = 0; 548 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK); 549 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen, 550 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 551 NFS_DEFAULT_NEGNAMETIMEO, 0, 0, NULL, 0)) != 0) { 552 printf("nfs_mountroot: mount %s on /: %d\n", path, error); 553 return (error); 554 } 555 return (0); 556 } 557 558 static void 559 nfs_sec_name(char *sec, int *flagsp) 560 { 561 if (!strcmp(sec, "krb5")) 562 *flagsp |= NFSMNT_KERB; 563 else if (!strcmp(sec, "krb5i")) 564 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY); 565 else if (!strcmp(sec, "krb5p")) 566 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY); 567 } 568 569 static void 570 nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp, 571 const char *hostname, struct ucred *cred, struct thread *td) 572 { 573 int adjsock; 574 char *p; 575 576 /* 577 * Set read-only flag if requested; otherwise, clear it if this is 578 * an update. If this is not an update, then either the read-only 579 * flag is already clear, or this is a root mount and it was set 580 * intentionally at some previous point. 581 */ 582 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) { 583 MNT_ILOCK(mp); 584 mp->mnt_flag |= MNT_RDONLY; 585 MNT_IUNLOCK(mp); 586 } else if (mp->mnt_flag & MNT_UPDATE) { 587 MNT_ILOCK(mp); 588 mp->mnt_flag &= ~MNT_RDONLY; 589 MNT_IUNLOCK(mp); 590 } 591 592 /* 593 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 594 * no sense in that context. Also, set up appropriate retransmit 595 * and soft timeout behavior. 596 */ 597 if (argp->sotype == SOCK_STREAM) { 598 nmp->nm_flag &= ~NFSMNT_NOCONN; 599 nmp->nm_timeo = NFS_MAXTIMEO; 600 if ((argp->flags & NFSMNT_NFSV4) != 0) 601 nmp->nm_retry = INT_MAX; 602 else 603 nmp->nm_retry = NFS_RETRANS_TCP; 604 } 605 606 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */ 607 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) { 608 argp->flags &= ~NFSMNT_RDIRPLUS; 609 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 610 } 611 612 /* Clear ONEOPENOWN for NFSv2, 3 and 4.0. */ 613 if (nmp->nm_minorvers == 0) { 614 argp->flags &= ~NFSMNT_ONEOPENOWN; 615 nmp->nm_flag &= ~NFSMNT_ONEOPENOWN; 616 } 617 618 /* Re-bind if rsrvd port requested and wasn't on one */ 619 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) 620 && (argp->flags & NFSMNT_RESVPORT); 621 /* Also re-bind if we're switching to/from a connected UDP socket */ 622 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != 623 (argp->flags & NFSMNT_NOCONN)); 624 625 /* Update flags atomically. Don't change the lock bits. */ 626 nmp->nm_flag = argp->flags | nmp->nm_flag; 627 628 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 629 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 630 if (nmp->nm_timeo < NFS_MINTIMEO) 631 nmp->nm_timeo = NFS_MINTIMEO; 632 else if (nmp->nm_timeo > NFS_MAXTIMEO) 633 nmp->nm_timeo = NFS_MAXTIMEO; 634 } 635 636 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 637 nmp->nm_retry = argp->retrans; 638 if (nmp->nm_retry > NFS_MAXREXMIT) 639 nmp->nm_retry = NFS_MAXREXMIT; 640 } 641 642 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 643 nmp->nm_wsize = argp->wsize; 644 /* 645 * Clip at the power of 2 below the size. There is an 646 * issue (not isolated) that causes intermittent page 647 * faults if this is not done. 648 */ 649 if (nmp->nm_wsize > NFS_FABLKSIZE) 650 nmp->nm_wsize = 1 << (fls(nmp->nm_wsize) - 1); 651 else 652 nmp->nm_wsize = NFS_FABLKSIZE; 653 } 654 655 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 656 nmp->nm_rsize = argp->rsize; 657 /* 658 * Clip at the power of 2 below the size. There is an 659 * issue (not isolated) that causes intermittent page 660 * faults if this is not done. 661 */ 662 if (nmp->nm_rsize > NFS_FABLKSIZE) 663 nmp->nm_rsize = 1 << (fls(nmp->nm_rsize) - 1); 664 else 665 nmp->nm_rsize = NFS_FABLKSIZE; 666 } 667 668 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 669 nmp->nm_readdirsize = argp->readdirsize; 670 } 671 672 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) 673 nmp->nm_acregmin = argp->acregmin; 674 else 675 nmp->nm_acregmin = NFS_MINATTRTIMO; 676 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) 677 nmp->nm_acregmax = argp->acregmax; 678 else 679 nmp->nm_acregmax = NFS_MAXATTRTIMO; 680 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) 681 nmp->nm_acdirmin = argp->acdirmin; 682 else 683 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; 684 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) 685 nmp->nm_acdirmax = argp->acdirmax; 686 else 687 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; 688 if (nmp->nm_acdirmin > nmp->nm_acdirmax) 689 nmp->nm_acdirmin = nmp->nm_acdirmax; 690 if (nmp->nm_acregmin > nmp->nm_acregmax) 691 nmp->nm_acregmin = nmp->nm_acregmax; 692 693 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) { 694 if (argp->readahead <= NFS_MAXRAHEAD) 695 nmp->nm_readahead = argp->readahead; 696 else 697 nmp->nm_readahead = NFS_MAXRAHEAD; 698 } 699 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) { 700 if (argp->wcommitsize < nmp->nm_wsize) 701 nmp->nm_wcommitsize = nmp->nm_wsize; 702 else 703 nmp->nm_wcommitsize = argp->wcommitsize; 704 } 705 706 adjsock |= ((nmp->nm_sotype != argp->sotype) || 707 (nmp->nm_soproto != argp->proto)); 708 709 if (nmp->nm_client != NULL && adjsock) { 710 int haslock = 0, error = 0; 711 712 if (nmp->nm_sotype == SOCK_STREAM) { 713 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock); 714 if (!error) 715 haslock = 1; 716 } 717 if (!error) { 718 newnfs_disconnect(nmp, &nmp->nm_sockreq); 719 if (haslock) 720 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock); 721 nmp->nm_sotype = argp->sotype; 722 nmp->nm_soproto = argp->proto; 723 if (nmp->nm_sotype == SOCK_DGRAM) 724 while (newnfs_connect(nmp, &nmp->nm_sockreq, 725 cred, td, 0, false, &nmp->nm_sockreq.nr_client)) { 726 printf("newnfs_args: retrying connect\n"); 727 (void) nfs_catnap(PSOCK, 0, "nfscon"); 728 } 729 } 730 } else { 731 nmp->nm_sotype = argp->sotype; 732 nmp->nm_soproto = argp->proto; 733 } 734 735 if (hostname != NULL) { 736 strlcpy(nmp->nm_hostname, hostname, 737 sizeof(nmp->nm_hostname)); 738 p = strchr(nmp->nm_hostname, ':'); 739 if (p != NULL) 740 *p = '\0'; 741 } 742 } 743 744 static const char *nfs_opts[] = { "from", "nfs_args", 745 "noac", "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union", 746 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update", 747 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus", 748 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize", 749 "retrans", "actimeo", "acregmin", "acregmax", "acdirmin", "acdirmax", 750 "resvport", "readahead", "hostname", "timeo", "timeout", "addr", "fh", 751 "nfsv3", "sec", "principal", "nfsv4", "gssname", "allgssname", "dirpath", 752 "minorversion", "nametimeo", "negnametimeo", "nocto", "noncontigwr", 753 "pnfs", "wcommitsize", "oneopenown", "tls", "tlscertname", "nconnect", 754 NULL }; 755 756 /* 757 * Parse the "from" mountarg, passed by the generic mount(8) program 758 * or the mountroot code. This is used when rerooting into NFS. 759 * 760 * Note that the "hostname" is actually a "hostname:/share/path" string. 761 */ 762 static int 763 nfs_mount_parse_from(struct vfsoptlist *opts, char **hostnamep, 764 struct sockaddr_in **sinp, char *dirpath, size_t dirpathsize, int *dirlenp) 765 { 766 char *nam, *delimp, *hostp, *spec; 767 int error, have_bracket = 0, offset, rv, speclen; 768 struct sockaddr_in *sin; 769 size_t len; 770 771 error = vfs_getopt(opts, "from", (void **)&spec, &speclen); 772 if (error != 0) 773 return (error); 774 nam = malloc(MNAMELEN + 1, M_TEMP, M_WAITOK); 775 776 /* 777 * This part comes from sbin/mount_nfs/mount_nfs.c:getnfsargs(). 778 */ 779 if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL && 780 *(delimp + 1) == ':') { 781 hostp = spec + 1; 782 spec = delimp + 2; 783 have_bracket = 1; 784 } else if ((delimp = strrchr(spec, ':')) != NULL) { 785 hostp = spec; 786 spec = delimp + 1; 787 } else if ((delimp = strrchr(spec, '@')) != NULL) { 788 printf("%s: path@server syntax is deprecated, " 789 "use server:path\n", __func__); 790 hostp = delimp + 1; 791 } else { 792 printf("%s: no <host>:<dirpath> nfs-name\n", __func__); 793 free(nam, M_TEMP); 794 return (EINVAL); 795 } 796 *delimp = '\0'; 797 798 /* 799 * If there has been a trailing slash at mounttime it seems 800 * that some mountd implementations fail to remove the mount 801 * entries from their mountlist while unmounting. 802 */ 803 for (speclen = strlen(spec); 804 speclen > 1 && spec[speclen - 1] == '/'; 805 speclen--) 806 spec[speclen - 1] = '\0'; 807 if (strlen(hostp) + strlen(spec) + 1 > MNAMELEN) { 808 printf("%s: %s:%s: name too long", __func__, hostp, spec); 809 free(nam, M_TEMP); 810 return (EINVAL); 811 } 812 /* Make both '@' and ':' notations equal */ 813 if (*hostp != '\0') { 814 len = strlen(hostp); 815 offset = 0; 816 if (have_bracket) 817 nam[offset++] = '['; 818 memmove(nam + offset, hostp, len); 819 if (have_bracket) 820 nam[len + offset++] = ']'; 821 nam[len + offset++] = ':'; 822 memmove(nam + len + offset, spec, speclen); 823 nam[len + speclen + offset] = '\0'; 824 } else 825 nam[0] = '\0'; 826 827 /* 828 * XXX: IPv6 829 */ 830 sin = malloc(sizeof(*sin), M_SONAME, M_WAITOK); 831 rv = inet_pton(AF_INET, hostp, &sin->sin_addr); 832 if (rv != 1) { 833 printf("%s: cannot parse '%s', inet_pton() returned %d\n", 834 __func__, hostp, rv); 835 free(nam, M_TEMP); 836 free(sin, M_SONAME); 837 return (EINVAL); 838 } 839 840 sin->sin_len = sizeof(*sin); 841 sin->sin_family = AF_INET; 842 /* 843 * XXX: hardcoded port number. 844 */ 845 sin->sin_port = htons(2049); 846 847 *hostnamep = strdup(nam, M_NEWNFSMNT); 848 *sinp = sin; 849 strlcpy(dirpath, spec, dirpathsize); 850 *dirlenp = strlen(dirpath); 851 852 free(nam, M_TEMP); 853 return (0); 854 } 855 856 /* 857 * VFS Operations. 858 * 859 * mount system call 860 * It seems a bit dumb to copyinstr() the host and path here and then 861 * bcopy() them in mountnfs(), but I wanted to detect errors before 862 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and 863 * an error after that means that I have to release the mbuf. 864 */ 865 /* ARGSUSED */ 866 static int 867 nfs_mount(struct mount *mp) 868 { 869 struct nfs_args args = { 870 .version = NFS_ARGSVERSION, 871 .addr = NULL, 872 .addrlen = sizeof (struct sockaddr_in), 873 .sotype = SOCK_STREAM, 874 .proto = 0, 875 .fh = NULL, 876 .fhsize = 0, 877 .flags = NFSMNT_RESVPORT, 878 .wsize = NFS_WSIZE, 879 .rsize = NFS_RSIZE, 880 .readdirsize = NFS_READDIRSIZE, 881 .timeo = 10, 882 .retrans = NFS_RETRANS, 883 .readahead = NFS_DEFRAHEAD, 884 .wcommitsize = 0, /* was: NQ_DEFLEASE */ 885 .hostname = NULL, 886 .acregmin = NFS_MINATTRTIMO, 887 .acregmax = NFS_MAXATTRTIMO, 888 .acdirmin = NFS_MINDIRATTRTIMO, 889 .acdirmax = NFS_MAXDIRATTRTIMO, 890 }; 891 int error = 0, ret, len; 892 struct sockaddr *nam = NULL; 893 struct vnode *vp; 894 struct thread *td; 895 char *hst; 896 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100]; 897 char *cp, *opt, *name, *secname, *tlscertname; 898 int nametimeo = NFS_DEFAULT_NAMETIMEO; 899 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO; 900 int minvers = -1; 901 int dirlen, has_nfs_args_opt, has_nfs_from_opt, 902 krbnamelen, srvkrbnamelen; 903 size_t hstlen; 904 uint32_t newflag; 905 int aconn = 0; 906 907 has_nfs_args_opt = 0; 908 has_nfs_from_opt = 0; 909 newflag = 0; 910 tlscertname = NULL; 911 hst = malloc(MNAMELEN, M_TEMP, M_WAITOK); 912 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) { 913 error = EINVAL; 914 goto out; 915 } 916 917 td = curthread; 918 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS && 919 nfs_diskless_valid != 0) { 920 error = nfs_mountroot(mp); 921 goto out; 922 } 923 924 nfscl_init(); 925 926 /* 927 * The old mount_nfs program passed the struct nfs_args 928 * from userspace to kernel. The new mount_nfs program 929 * passes string options via nmount() from userspace to kernel 930 * and we populate the struct nfs_args in the kernel. 931 */ 932 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) { 933 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, 934 sizeof(args)); 935 if (error != 0) 936 goto out; 937 938 if (args.version != NFS_ARGSVERSION) { 939 error = EPROGMISMATCH; 940 goto out; 941 } 942 has_nfs_args_opt = 1; 943 } 944 945 /* Handle the new style options. */ 946 if (vfs_getopt(mp->mnt_optnew, "noac", NULL, NULL) == 0) { 947 args.acdirmin = args.acdirmax = 948 args.acregmin = args.acregmax = 0; 949 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX | 950 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX; 951 } 952 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0) 953 args.flags |= NFSMNT_NOCONN; 954 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0) 955 args.flags &= ~NFSMNT_NOCONN; 956 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0) 957 args.flags |= NFSMNT_NOLOCKD; 958 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0) 959 args.flags &= ~NFSMNT_NOLOCKD; 960 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0) 961 args.flags |= NFSMNT_INT; 962 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0) 963 args.flags |= NFSMNT_RDIRPLUS; 964 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0) 965 args.flags |= NFSMNT_RESVPORT; 966 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0) 967 args.flags &= ~NFSMNT_RESVPORT; 968 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0) 969 args.flags |= NFSMNT_SOFT; 970 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0) 971 args.flags &= ~NFSMNT_SOFT; 972 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0) 973 args.sotype = SOCK_DGRAM; 974 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0) 975 args.sotype = SOCK_DGRAM; 976 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0) 977 args.sotype = SOCK_STREAM; 978 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0) 979 args.flags |= NFSMNT_NFSV3; 980 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) { 981 args.flags |= NFSMNT_NFSV4; 982 args.sotype = SOCK_STREAM; 983 } 984 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0) 985 args.flags |= NFSMNT_ALLGSSNAME; 986 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0) 987 args.flags |= NFSMNT_NOCTO; 988 if (vfs_getopt(mp->mnt_optnew, "noncontigwr", NULL, NULL) == 0) 989 args.flags |= NFSMNT_NONCONTIGWR; 990 if (vfs_getopt(mp->mnt_optnew, "pnfs", NULL, NULL) == 0) 991 args.flags |= NFSMNT_PNFS; 992 if (vfs_getopt(mp->mnt_optnew, "oneopenown", NULL, NULL) == 0) 993 args.flags |= NFSMNT_ONEOPENOWN; 994 if (vfs_getopt(mp->mnt_optnew, "tls", NULL, NULL) == 0) 995 newflag |= NFSMNT_TLS; 996 if (vfs_getopt(mp->mnt_optnew, "tlscertname", (void **)&opt, &len) == 997 0) { 998 /* 999 * tlscertname with "key.pem" appended to it forms a file 1000 * name. As such, the maximum allowable strlen(tlscertname) is 1001 * NAME_MAX - 7. However, "len" includes the nul termination 1002 * byte so it can be up to NAME_MAX - 6. 1003 */ 1004 if (opt == NULL || len <= 1 || len > NAME_MAX - 6) { 1005 vfs_mount_error(mp, "invalid tlscertname"); 1006 error = EINVAL; 1007 goto out; 1008 } 1009 tlscertname = malloc(len, M_NEWNFSMNT, M_WAITOK); 1010 strlcpy(tlscertname, opt, len); 1011 } 1012 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) { 1013 if (opt == NULL) { 1014 vfs_mount_error(mp, "illegal readdirsize"); 1015 error = EINVAL; 1016 goto out; 1017 } 1018 ret = sscanf(opt, "%d", &args.readdirsize); 1019 if (ret != 1 || args.readdirsize <= 0) { 1020 vfs_mount_error(mp, "illegal readdirsize: %s", 1021 opt); 1022 error = EINVAL; 1023 goto out; 1024 } 1025 args.flags |= NFSMNT_READDIRSIZE; 1026 } 1027 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) { 1028 if (opt == NULL) { 1029 vfs_mount_error(mp, "illegal readahead"); 1030 error = EINVAL; 1031 goto out; 1032 } 1033 ret = sscanf(opt, "%d", &args.readahead); 1034 if (ret != 1 || args.readahead <= 0) { 1035 vfs_mount_error(mp, "illegal readahead: %s", 1036 opt); 1037 error = EINVAL; 1038 goto out; 1039 } 1040 args.flags |= NFSMNT_READAHEAD; 1041 } 1042 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) { 1043 if (opt == NULL) { 1044 vfs_mount_error(mp, "illegal wsize"); 1045 error = EINVAL; 1046 goto out; 1047 } 1048 ret = sscanf(opt, "%d", &args.wsize); 1049 if (ret != 1 || args.wsize <= 0) { 1050 vfs_mount_error(mp, "illegal wsize: %s", 1051 opt); 1052 error = EINVAL; 1053 goto out; 1054 } 1055 args.flags |= NFSMNT_WSIZE; 1056 } 1057 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) { 1058 if (opt == NULL) { 1059 vfs_mount_error(mp, "illegal rsize"); 1060 error = EINVAL; 1061 goto out; 1062 } 1063 ret = sscanf(opt, "%d", &args.rsize); 1064 if (ret != 1 || args.rsize <= 0) { 1065 vfs_mount_error(mp, "illegal wsize: %s", 1066 opt); 1067 error = EINVAL; 1068 goto out; 1069 } 1070 args.flags |= NFSMNT_RSIZE; 1071 } 1072 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) { 1073 if (opt == NULL) { 1074 vfs_mount_error(mp, "illegal retrans"); 1075 error = EINVAL; 1076 goto out; 1077 } 1078 ret = sscanf(opt, "%d", &args.retrans); 1079 if (ret != 1 || args.retrans <= 0) { 1080 vfs_mount_error(mp, "illegal retrans: %s", 1081 opt); 1082 error = EINVAL; 1083 goto out; 1084 } 1085 args.flags |= NFSMNT_RETRANS; 1086 } 1087 if (vfs_getopt(mp->mnt_optnew, "actimeo", (void **)&opt, NULL) == 0) { 1088 ret = sscanf(opt, "%d", &args.acregmin); 1089 if (ret != 1 || args.acregmin < 0) { 1090 vfs_mount_error(mp, "illegal actimeo: %s", 1091 opt); 1092 error = EINVAL; 1093 goto out; 1094 } 1095 args.acdirmin = args.acdirmax = args.acregmax = args.acregmin; 1096 args.flags |= NFSMNT_ACDIRMIN | NFSMNT_ACDIRMAX | 1097 NFSMNT_ACREGMIN | NFSMNT_ACREGMAX; 1098 } 1099 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) { 1100 ret = sscanf(opt, "%d", &args.acregmin); 1101 if (ret != 1 || args.acregmin < 0) { 1102 vfs_mount_error(mp, "illegal acregmin: %s", 1103 opt); 1104 error = EINVAL; 1105 goto out; 1106 } 1107 args.flags |= NFSMNT_ACREGMIN; 1108 } 1109 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) { 1110 ret = sscanf(opt, "%d", &args.acregmax); 1111 if (ret != 1 || args.acregmax < 0) { 1112 vfs_mount_error(mp, "illegal acregmax: %s", 1113 opt); 1114 error = EINVAL; 1115 goto out; 1116 } 1117 args.flags |= NFSMNT_ACREGMAX; 1118 } 1119 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) { 1120 ret = sscanf(opt, "%d", &args.acdirmin); 1121 if (ret != 1 || args.acdirmin < 0) { 1122 vfs_mount_error(mp, "illegal acdirmin: %s", 1123 opt); 1124 error = EINVAL; 1125 goto out; 1126 } 1127 args.flags |= NFSMNT_ACDIRMIN; 1128 } 1129 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) { 1130 ret = sscanf(opt, "%d", &args.acdirmax); 1131 if (ret != 1 || args.acdirmax < 0) { 1132 vfs_mount_error(mp, "illegal acdirmax: %s", 1133 opt); 1134 error = EINVAL; 1135 goto out; 1136 } 1137 args.flags |= NFSMNT_ACDIRMAX; 1138 } 1139 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) { 1140 ret = sscanf(opt, "%d", &args.wcommitsize); 1141 if (ret != 1 || args.wcommitsize < 0) { 1142 vfs_mount_error(mp, "illegal wcommitsize: %s", opt); 1143 error = EINVAL; 1144 goto out; 1145 } 1146 args.flags |= NFSMNT_WCOMMITSIZE; 1147 } 1148 if (vfs_getopt(mp->mnt_optnew, "timeo", (void **)&opt, NULL) == 0) { 1149 ret = sscanf(opt, "%d", &args.timeo); 1150 if (ret != 1 || args.timeo <= 0) { 1151 vfs_mount_error(mp, "illegal timeo: %s", 1152 opt); 1153 error = EINVAL; 1154 goto out; 1155 } 1156 args.flags |= NFSMNT_TIMEO; 1157 } 1158 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) { 1159 ret = sscanf(opt, "%d", &args.timeo); 1160 if (ret != 1 || args.timeo <= 0) { 1161 vfs_mount_error(mp, "illegal timeout: %s", 1162 opt); 1163 error = EINVAL; 1164 goto out; 1165 } 1166 args.flags |= NFSMNT_TIMEO; 1167 } 1168 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) { 1169 ret = sscanf(opt, "%d", &nametimeo); 1170 if (ret != 1 || nametimeo < 0) { 1171 vfs_mount_error(mp, "illegal nametimeo: %s", opt); 1172 error = EINVAL; 1173 goto out; 1174 } 1175 } 1176 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL) 1177 == 0) { 1178 ret = sscanf(opt, "%d", &negnametimeo); 1179 if (ret != 1 || negnametimeo < 0) { 1180 vfs_mount_error(mp, "illegal negnametimeo: %s", 1181 opt); 1182 error = EINVAL; 1183 goto out; 1184 } 1185 } 1186 if (vfs_getopt(mp->mnt_optnew, "minorversion", (void **)&opt, NULL) == 1187 0) { 1188 ret = sscanf(opt, "%d", &minvers); 1189 if (ret != 1 || minvers < 0 || minvers > 2 || 1190 (args.flags & NFSMNT_NFSV4) == 0) { 1191 vfs_mount_error(mp, "illegal minorversion: %s", opt); 1192 error = EINVAL; 1193 goto out; 1194 } 1195 } 1196 if (vfs_getopt(mp->mnt_optnew, "nconnect", (void **)&opt, NULL) == 1197 0) { 1198 ret = sscanf(opt, "%d", &aconn); 1199 if (ret != 1 || aconn < 1 || aconn > NFS_MAXNCONN) { 1200 vfs_mount_error(mp, "illegal nconnect: %s", opt); 1201 error = EINVAL; 1202 goto out; 1203 } 1204 /* 1205 * Setting nconnect=1 is a no-op, allowed so that 1206 * the option can be used in a Linux compatible way. 1207 */ 1208 aconn--; 1209 } 1210 if (vfs_getopt(mp->mnt_optnew, "sec", 1211 (void **) &secname, NULL) == 0) 1212 nfs_sec_name(secname, &args.flags); 1213 1214 if (mp->mnt_flag & MNT_UPDATE) { 1215 struct nfsmount *nmp = VFSTONFS(mp); 1216 1217 if (nmp == NULL) { 1218 error = EIO; 1219 goto out; 1220 } 1221 1222 /* 1223 * If a change from TCP->UDP is done and there are thread(s) 1224 * that have I/O RPC(s) in progress with a transfer size 1225 * greater than NFS_MAXDGRAMDATA, those thread(s) will be 1226 * hung, retrying the RPC(s) forever. Usually these threads 1227 * will be seen doing an uninterruptible sleep on wait channel 1228 * "nfsreq". 1229 */ 1230 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM) 1231 tprintf(td->td_proc, LOG_WARNING, 1232 "Warning: mount -u that changes TCP->UDP can result in hung threads\n"); 1233 1234 /* 1235 * When doing an update, we can't change version, 1236 * security, switch lockd strategies, change cookie 1237 * translation or switch oneopenown. 1238 */ 1239 args.flags = (args.flags & 1240 ~(NFSMNT_NFSV3 | 1241 NFSMNT_NFSV4 | 1242 NFSMNT_KERB | 1243 NFSMNT_INTEGRITY | 1244 NFSMNT_PRIVACY | 1245 NFSMNT_ONEOPENOWN | 1246 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) | 1247 (nmp->nm_flag & 1248 (NFSMNT_NFSV3 | 1249 NFSMNT_NFSV4 | 1250 NFSMNT_KERB | 1251 NFSMNT_INTEGRITY | 1252 NFSMNT_PRIVACY | 1253 NFSMNT_ONEOPENOWN | 1254 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)); 1255 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td); 1256 goto out; 1257 } 1258 1259 /* 1260 * Make the nfs_ip_paranoia sysctl serve as the default connection 1261 * or no-connection mode for those protocols that support 1262 * no-connection mode (the flag will be cleared later for protocols 1263 * that do not support no-connection mode). This will allow a client 1264 * to receive replies from a different IP then the request was 1265 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid), 1266 * not 0. 1267 */ 1268 if (nfs_ip_paranoia == 0) 1269 args.flags |= NFSMNT_NOCONN; 1270 1271 if (has_nfs_args_opt != 0) { 1272 /* 1273 * In the 'nfs_args' case, the pointers in the args 1274 * structure are in userland - we copy them in here. 1275 */ 1276 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) { 1277 vfs_mount_error(mp, "Bad file handle"); 1278 error = EINVAL; 1279 goto out; 1280 } 1281 error = copyin((caddr_t)args.fh, (caddr_t)nfh, 1282 args.fhsize); 1283 if (error != 0) 1284 goto out; 1285 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen); 1286 if (error != 0) 1287 goto out; 1288 bzero(&hst[hstlen], MNAMELEN - hstlen); 1289 args.hostname = hst; 1290 /* getsockaddr() call must be after above copyin() calls */ 1291 error = getsockaddr(&nam, args.addr, args.addrlen); 1292 if (error != 0) 1293 goto out; 1294 } else if (nfs_mount_parse_from(mp->mnt_optnew, 1295 &args.hostname, (struct sockaddr_in **)&nam, dirpath, 1296 sizeof(dirpath), &dirlen) == 0) { 1297 has_nfs_from_opt = 1; 1298 bcopy(args.hostname, hst, MNAMELEN); 1299 hst[MNAMELEN - 1] = '\0'; 1300 1301 /* 1302 * This only works with NFSv4 for now. 1303 */ 1304 args.fhsize = 0; 1305 args.flags |= NFSMNT_NFSV4; 1306 args.sotype = SOCK_STREAM; 1307 } else { 1308 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh, 1309 &args.fhsize) == 0) { 1310 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) { 1311 vfs_mount_error(mp, "Bad file handle"); 1312 error = EINVAL; 1313 goto out; 1314 } 1315 bcopy(args.fh, nfh, args.fhsize); 1316 } else { 1317 args.fhsize = 0; 1318 } 1319 (void) vfs_getopt(mp->mnt_optnew, "hostname", 1320 (void **)&args.hostname, &len); 1321 if (args.hostname == NULL) { 1322 vfs_mount_error(mp, "Invalid hostname"); 1323 error = EINVAL; 1324 goto out; 1325 } 1326 if (len >= MNAMELEN) { 1327 vfs_mount_error(mp, "Hostname too long"); 1328 error = EINVAL; 1329 goto out; 1330 } 1331 bcopy(args.hostname, hst, len); 1332 hst[len] = '\0'; 1333 } 1334 1335 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0) 1336 strlcpy(srvkrbname, name, sizeof (srvkrbname)); 1337 else { 1338 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst); 1339 cp = strchr(srvkrbname, ':'); 1340 if (cp != NULL) 1341 *cp = '\0'; 1342 } 1343 srvkrbnamelen = strlen(srvkrbname); 1344 1345 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0) 1346 strlcpy(krbname, name, sizeof (krbname)); 1347 else 1348 krbname[0] = '\0'; 1349 krbnamelen = strlen(krbname); 1350 1351 if (has_nfs_from_opt == 0) { 1352 if (vfs_getopt(mp->mnt_optnew, 1353 "dirpath", (void **)&name, NULL) == 0) 1354 strlcpy(dirpath, name, sizeof (dirpath)); 1355 else 1356 dirpath[0] = '\0'; 1357 dirlen = strlen(dirpath); 1358 } 1359 1360 if (has_nfs_args_opt == 0 && has_nfs_from_opt == 0) { 1361 if (vfs_getopt(mp->mnt_optnew, "addr", 1362 (void **)&args.addr, &args.addrlen) == 0) { 1363 if (args.addrlen > SOCK_MAXADDRLEN) { 1364 error = ENAMETOOLONG; 1365 goto out; 1366 } 1367 nam = malloc(args.addrlen, M_SONAME, M_WAITOK); 1368 bcopy(args.addr, nam, args.addrlen); 1369 nam->sa_len = args.addrlen; 1370 } else { 1371 vfs_mount_error(mp, "No server address"); 1372 error = EINVAL; 1373 goto out; 1374 } 1375 } 1376 1377 if (aconn > 0 && (args.sotype != SOCK_STREAM || 1378 (args.flags & NFSMNT_NFSV4) == 0 || minvers == 0)) { 1379 /* 1380 * RFC 5661 requires that an NFSv4.1/4.2 server 1381 * send an RPC reply on the same TCP connection 1382 * as the one it received the request on. 1383 * This property in required for "nconnect" and 1384 * might not be the case for NFSv3 or NFSv4.0 servers. 1385 */ 1386 vfs_mount_error(mp, "nconnect should only be used " 1387 "for NFSv4.1/4.2 mounts"); 1388 error = EINVAL; 1389 goto out; 1390 } 1391 1392 args.fh = nfh; 1393 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath, 1394 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td, 1395 nametimeo, negnametimeo, minvers, newflag, tlscertname, aconn); 1396 out: 1397 if (!error) { 1398 MNT_ILOCK(mp); 1399 mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_NO_IOPF | 1400 MNTK_USES_BCACHE; 1401 if ((VFSTONFS(mp)->nm_flag & NFSMNT_NFSV4) != 0) 1402 mp->mnt_kern_flag |= MNTK_NULL_NOCACHE; 1403 MNT_IUNLOCK(mp); 1404 } 1405 free(hst, M_TEMP); 1406 return (error); 1407 } 1408 1409 /* 1410 * VFS Operations. 1411 * 1412 * mount system call 1413 * It seems a bit dumb to copyinstr() the host and path here and then 1414 * bcopy() them in mountnfs(), but I wanted to detect errors before 1415 * doing the getsockaddr() call because getsockaddr() allocates an mbuf and 1416 * an error after that means that I have to release the mbuf. 1417 */ 1418 /* ARGSUSED */ 1419 static int 1420 nfs_cmount(struct mntarg *ma, void *data, uint64_t flags) 1421 { 1422 int error; 1423 struct nfs_args args; 1424 1425 error = copyin(data, &args, sizeof (struct nfs_args)); 1426 if (error) 1427 return error; 1428 1429 ma = mount_arg(ma, "nfs_args", &args, sizeof args); 1430 1431 error = kernel_mount(ma, flags); 1432 return (error); 1433 } 1434 1435 /* 1436 * Common code for mount and mountroot 1437 */ 1438 static int 1439 mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, 1440 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen, 1441 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp, 1442 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo, 1443 int minvers, uint32_t newflag, char *tlscertname, int aconn) 1444 { 1445 struct nfsmount *nmp; 1446 struct nfsnode *np; 1447 int error, trycnt, ret; 1448 struct nfsvattr nfsva; 1449 struct nfsclclient *clp; 1450 struct nfsclds *dsp, *tdsp; 1451 uint32_t lease; 1452 bool tryminvers; 1453 static u_int64_t clval = 0; 1454 #ifdef KERN_TLS 1455 u_int maxlen; 1456 #endif 1457 1458 NFSCL_DEBUG(3, "in mnt\n"); 1459 clp = NULL; 1460 if (mp->mnt_flag & MNT_UPDATE) { 1461 nmp = VFSTONFS(mp); 1462 printf("%s: MNT_UPDATE is no longer handled here\n", __func__); 1463 free(nam, M_SONAME); 1464 free(tlscertname, M_NEWNFSMNT); 1465 return (0); 1466 } else { 1467 /* NFS-over-TLS requires that rpctls be functioning. */ 1468 if ((newflag & NFSMNT_TLS) != 0) { 1469 error = EINVAL; 1470 #ifdef KERN_TLS 1471 /* KERN_TLS is only supported for TCP. */ 1472 if (argp->sotype == SOCK_STREAM && 1473 rpctls_getinfo(&maxlen, true, false)) 1474 error = 0; 1475 #endif 1476 if (error != 0) { 1477 free(nam, M_SONAME); 1478 free(tlscertname, M_NEWNFSMNT); 1479 return (error); 1480 } 1481 } 1482 nmp = malloc(sizeof (struct nfsmount) + 1483 krbnamelen + dirlen + srvkrbnamelen + 2, 1484 M_NEWNFSMNT, M_WAITOK | M_ZERO); 1485 nmp->nm_tlscertname = tlscertname; 1486 nmp->nm_newflag = newflag; 1487 TAILQ_INIT(&nmp->nm_bufq); 1488 TAILQ_INIT(&nmp->nm_sess); 1489 if (clval == 0) 1490 clval = (u_int64_t)nfsboottime.tv_sec; 1491 nmp->nm_clval = clval++; 1492 nmp->nm_krbnamelen = krbnamelen; 1493 nmp->nm_dirpathlen = dirlen; 1494 nmp->nm_srvkrbnamelen = srvkrbnamelen; 1495 if (td->td_ucred->cr_uid != (uid_t)0) { 1496 /* 1497 * nm_uid is used to get KerberosV credentials for 1498 * the nfsv4 state handling operations if there is 1499 * no host based principal set. Use the uid of 1500 * this user if not root, since they are doing the 1501 * mount. I don't think setting this for root will 1502 * work, since root normally does not have user 1503 * credentials in a credentials cache. 1504 */ 1505 nmp->nm_uid = td->td_ucred->cr_uid; 1506 } else { 1507 /* 1508 * Just set to -1, so it won't be used. 1509 */ 1510 nmp->nm_uid = (uid_t)-1; 1511 } 1512 1513 /* Copy and null terminate all the names */ 1514 if (nmp->nm_krbnamelen > 0) { 1515 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen); 1516 nmp->nm_name[nmp->nm_krbnamelen] = '\0'; 1517 } 1518 if (nmp->nm_dirpathlen > 0) { 1519 bcopy(dirpath, NFSMNT_DIRPATH(nmp), 1520 nmp->nm_dirpathlen); 1521 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen 1522 + 1] = '\0'; 1523 } 1524 if (nmp->nm_srvkrbnamelen > 0) { 1525 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp), 1526 nmp->nm_srvkrbnamelen); 1527 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen 1528 + nmp->nm_srvkrbnamelen + 2] = '\0'; 1529 } 1530 nmp->nm_sockreq.nr_cred = crhold(cred); 1531 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF); 1532 mp->mnt_data = nmp; 1533 nmp->nm_getinfo = nfs_getnlminfo; 1534 nmp->nm_vinvalbuf = ncl_vinvalbuf; 1535 } 1536 vfs_getnewfsid(mp); 1537 nmp->nm_mountp = mp; 1538 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK); 1539 1540 /* 1541 * Since nfs_decode_args() might optionally set them, these 1542 * need to be set to defaults before the call, so that the 1543 * optional settings aren't overwritten. 1544 */ 1545 nmp->nm_nametimeo = nametimeo; 1546 nmp->nm_negnametimeo = negnametimeo; 1547 nmp->nm_timeo = NFS_TIMEO; 1548 nmp->nm_retry = NFS_RETRANS; 1549 nmp->nm_readahead = NFS_DEFRAHEAD; 1550 1551 /* This is empirical approximation of sqrt(hibufspace) * 256. */ 1552 nmp->nm_wcommitsize = NFS_MAXBSIZE / 256; 1553 while ((long)nmp->nm_wcommitsize * nmp->nm_wcommitsize < hibufspace) 1554 nmp->nm_wcommitsize *= 2; 1555 nmp->nm_wcommitsize *= 256; 1556 1557 tryminvers = false; 1558 if ((argp->flags & NFSMNT_NFSV4) != 0) { 1559 if (minvers < 0) { 1560 tryminvers = true; 1561 minvers = NFSV42_MINORVERSION; 1562 } 1563 nmp->nm_minorvers = minvers; 1564 } else 1565 nmp->nm_minorvers = 0; 1566 1567 nfs_decode_args(mp, nmp, argp, hst, cred, td); 1568 1569 /* 1570 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too 1571 * high, depending on whether we end up with negative offsets in 1572 * the client or server somewhere. 2GB-1 may be safer. 1573 * 1574 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum 1575 * that we can handle until we find out otherwise. 1576 */ 1577 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) 1578 nmp->nm_maxfilesize = 0xffffffffLL; 1579 else 1580 nmp->nm_maxfilesize = OFF_MAX; 1581 1582 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) { 1583 nmp->nm_wsize = NFS_WSIZE; 1584 nmp->nm_rsize = NFS_RSIZE; 1585 nmp->nm_readdirsize = NFS_READDIRSIZE; 1586 } 1587 nmp->nm_numgrps = NFS_MAXGRPS; 1588 nmp->nm_tprintf_delay = nfs_tprintf_delay; 1589 if (nmp->nm_tprintf_delay < 0) 1590 nmp->nm_tprintf_delay = 0; 1591 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay; 1592 if (nmp->nm_tprintf_initial_delay < 0) 1593 nmp->nm_tprintf_initial_delay = 0; 1594 nmp->nm_fhsize = argp->fhsize; 1595 if (nmp->nm_fhsize > 0) 1596 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); 1597 strlcpy(mp->mnt_stat.f_mntfromname, hst, MNAMELEN); 1598 nmp->nm_nam = nam; 1599 /* Set up the sockets and per-host congestion */ 1600 nmp->nm_sotype = argp->sotype; 1601 nmp->nm_soproto = argp->proto; 1602 nmp->nm_sockreq.nr_prog = NFS_PROG; 1603 if ((argp->flags & NFSMNT_NFSV4)) 1604 nmp->nm_sockreq.nr_vers = NFS_VER4; 1605 else if ((argp->flags & NFSMNT_NFSV3)) 1606 nmp->nm_sockreq.nr_vers = NFS_VER3; 1607 else 1608 nmp->nm_sockreq.nr_vers = NFS_VER2; 1609 1610 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0, false, 1611 &nmp->nm_sockreq.nr_client))) 1612 goto bad; 1613 /* For NFSv4, get the clientid now. */ 1614 if ((argp->flags & NFSMNT_NFSV4) != 0) { 1615 NFSCL_DEBUG(3, "at getcl\n"); 1616 error = nfscl_getcl(mp, cred, td, tryminvers, true, &clp); 1617 NFSCL_DEBUG(3, "aft getcl=%d\n", error); 1618 if (error != 0) 1619 goto bad; 1620 if (aconn > 0 && nmp->nm_minorvers == 0) { 1621 vfs_mount_error(mp, "nconnect should only be used " 1622 "for NFSv4.1/4.2 mounts"); 1623 error = EINVAL; 1624 goto bad; 1625 } 1626 } 1627 1628 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) && 1629 nmp->nm_dirpathlen > 0) { 1630 NFSCL_DEBUG(3, "in dirp\n"); 1631 /* 1632 * If the fhsize on the mount point == 0 for V4, the mount 1633 * path needs to be looked up. 1634 */ 1635 trycnt = 3; 1636 do { 1637 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp), 1638 cred, td); 1639 NFSCL_DEBUG(3, "aft dirp=%d\n", error); 1640 if (error) 1641 (void) nfs_catnap(PZERO, error, "nfsgetdirp"); 1642 } while (error && --trycnt > 0); 1643 if (error) 1644 goto bad; 1645 } 1646 1647 /* 1648 * A reference count is needed on the nfsnode representing the 1649 * remote root. If this object is not persistent, then backward 1650 * traversals of the mount point (i.e. "..") will not work if 1651 * the nfsnode gets flushed out of the cache. Ufs does not have 1652 * this problem, because one can identify root inodes by their 1653 * number == UFS_ROOTINO (2). 1654 */ 1655 if (nmp->nm_fhsize > 0) { 1656 /* 1657 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set 1658 * non-zero for the root vnode. f_iosize will be set correctly 1659 * by nfs_statfs() before any I/O occurs. 1660 */ 1661 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ; 1662 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, 1663 LK_EXCLUSIVE); 1664 if (error) 1665 goto bad; 1666 *vpp = NFSTOV(np); 1667 1668 /* 1669 * Get file attributes and transfer parameters for the 1670 * mountpoint. This has the side effect of filling in 1671 * (*vpp)->v_type with the correct value. 1672 */ 1673 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1, 1674 cred, td, &nfsva, NULL, &lease); 1675 if (ret) { 1676 /* 1677 * Just set default values to get things going. 1678 */ 1679 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr)); 1680 nfsva.na_vattr.va_type = VDIR; 1681 nfsva.na_vattr.va_mode = 0777; 1682 nfsva.na_vattr.va_nlink = 100; 1683 nfsva.na_vattr.va_uid = (uid_t)0; 1684 nfsva.na_vattr.va_gid = (gid_t)0; 1685 nfsva.na_vattr.va_fileid = 2; 1686 nfsva.na_vattr.va_gen = 1; 1687 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE; 1688 nfsva.na_vattr.va_size = 512 * 1024; 1689 lease = 60; 1690 } 1691 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1); 1692 if ((argp->flags & NFSMNT_NFSV4) != 0) { 1693 NFSCL_DEBUG(3, "lease=%d\n", (int)lease); 1694 NFSLOCKCLSTATE(); 1695 clp->nfsc_renew = NFSCL_RENEW(lease); 1696 clp->nfsc_expire = NFSD_MONOSEC + clp->nfsc_renew; 1697 clp->nfsc_clientidrev++; 1698 if (clp->nfsc_clientidrev == 0) 1699 clp->nfsc_clientidrev++; 1700 NFSUNLOCKCLSTATE(); 1701 /* 1702 * Mount will succeed, so the renew thread can be 1703 * started now. 1704 */ 1705 nfscl_start_renewthread(clp); 1706 nfscl_clientrelease(clp); 1707 } 1708 if (argp->flags & NFSMNT_NFSV3) 1709 ncl_fsinfo(nmp, *vpp, cred, td); 1710 1711 /* Mark if the mount point supports NFSv4 ACLs. */ 1712 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 && 1713 ret == 0 && 1714 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) { 1715 MNT_ILOCK(mp); 1716 mp->mnt_flag |= MNT_NFS4ACLS; 1717 MNT_IUNLOCK(mp); 1718 } 1719 1720 /* Can now allow additional connections. */ 1721 if (aconn > 0) 1722 nmp->nm_aconnect = aconn; 1723 1724 /* 1725 * Lose the lock but keep the ref. 1726 */ 1727 NFSVOPUNLOCK(*vpp); 1728 vfs_cache_root_set(mp, *vpp); 1729 return (0); 1730 } 1731 error = EIO; 1732 1733 bad: 1734 if (clp != NULL) 1735 nfscl_clientrelease(clp); 1736 newnfs_disconnect(NULL, &nmp->nm_sockreq); 1737 crfree(nmp->nm_sockreq.nr_cred); 1738 if (nmp->nm_sockreq.nr_auth != NULL) 1739 AUTH_DESTROY(nmp->nm_sockreq.nr_auth); 1740 mtx_destroy(&nmp->nm_sockreq.nr_mtx); 1741 mtx_destroy(&nmp->nm_mtx); 1742 if (nmp->nm_clp != NULL) { 1743 NFSLOCKCLSTATE(); 1744 LIST_REMOVE(nmp->nm_clp, nfsc_list); 1745 NFSUNLOCKCLSTATE(); 1746 free(nmp->nm_clp, M_NFSCLCLIENT); 1747 } 1748 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) { 1749 if (dsp != TAILQ_FIRST(&nmp->nm_sess) && 1750 dsp->nfsclds_sockp != NULL) 1751 newnfs_disconnect(NULL, dsp->nfsclds_sockp); 1752 nfscl_freenfsclds(dsp); 1753 } 1754 free(nmp->nm_tlscertname, M_NEWNFSMNT); 1755 free(nmp, M_NEWNFSMNT); 1756 free(nam, M_SONAME); 1757 return (error); 1758 } 1759 1760 /* 1761 * unmount system call 1762 */ 1763 static int 1764 nfs_unmount(struct mount *mp, int mntflags) 1765 { 1766 struct thread *td; 1767 struct nfsmount *nmp; 1768 int error, flags = 0, i, trycnt = 0; 1769 struct nfsclds *dsp, *tdsp; 1770 struct nfscldeleg *dp, *ndp; 1771 struct nfscldeleghead dh; 1772 1773 td = curthread; 1774 TAILQ_INIT(&dh); 1775 1776 if (mntflags & MNT_FORCE) 1777 flags |= FORCECLOSE; 1778 nmp = VFSTONFS(mp); 1779 error = 0; 1780 /* 1781 * Goes something like this.. 1782 * - Call vflush() to clear out vnodes for this filesystem 1783 * - Close the socket 1784 * - Free up the data structures 1785 */ 1786 /* In the forced case, cancel any outstanding requests. */ 1787 if (mntflags & MNT_FORCE) { 1788 NFSDDSLOCK(); 1789 if (nfsv4_findmirror(nmp) != NULL) 1790 error = ENXIO; 1791 NFSDDSUNLOCK(); 1792 if (error) 1793 goto out; 1794 error = newnfs_nmcancelreqs(nmp); 1795 if (error) 1796 goto out; 1797 /* For a forced close, get rid of the renew thread now */ 1798 nfscl_umount(nmp, td, &dh); 1799 } 1800 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */ 1801 do { 1802 error = vflush(mp, 1, flags, td); 1803 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30) 1804 (void) nfs_catnap(PSOCK, error, "newndm"); 1805 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30); 1806 if (error) 1807 goto out; 1808 1809 /* 1810 * We are now committed to the unmount. 1811 */ 1812 if ((mntflags & MNT_FORCE) == 0) 1813 nfscl_umount(nmp, td, NULL); 1814 else { 1815 mtx_lock(&nmp->nm_mtx); 1816 nmp->nm_privflag |= NFSMNTP_FORCEDISM; 1817 mtx_unlock(&nmp->nm_mtx); 1818 } 1819 /* Make sure no nfsiods are assigned to this mount. */ 1820 NFSLOCKIOD(); 1821 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 1822 if (ncl_iodmount[i] == nmp) { 1823 ncl_iodwant[i] = NFSIOD_AVAILABLE; 1824 ncl_iodmount[i] = NULL; 1825 } 1826 NFSUNLOCKIOD(); 1827 1828 /* 1829 * We can now set mnt_data to NULL and wait for 1830 * nfssvc(NFSSVC_FORCEDISM) to complete. 1831 */ 1832 mtx_lock(&mountlist_mtx); 1833 mtx_lock(&nmp->nm_mtx); 1834 mp->mnt_data = NULL; 1835 mtx_unlock(&mountlist_mtx); 1836 while ((nmp->nm_privflag & NFSMNTP_CANCELRPCS) != 0) 1837 msleep(nmp, &nmp->nm_mtx, PVFS, "nfsfdism", 0); 1838 mtx_unlock(&nmp->nm_mtx); 1839 1840 newnfs_disconnect(nmp, &nmp->nm_sockreq); 1841 crfree(nmp->nm_sockreq.nr_cred); 1842 free(nmp->nm_nam, M_SONAME); 1843 if (nmp->nm_sockreq.nr_auth != NULL) 1844 AUTH_DESTROY(nmp->nm_sockreq.nr_auth); 1845 mtx_destroy(&nmp->nm_sockreq.nr_mtx); 1846 mtx_destroy(&nmp->nm_mtx); 1847 TAILQ_FOREACH_SAFE(dsp, &nmp->nm_sess, nfsclds_list, tdsp) { 1848 if (dsp != TAILQ_FIRST(&nmp->nm_sess) && 1849 dsp->nfsclds_sockp != NULL) 1850 newnfs_disconnect(NULL, dsp->nfsclds_sockp); 1851 nfscl_freenfsclds(dsp); 1852 } 1853 free(nmp->nm_tlscertname, M_NEWNFSMNT); 1854 free(nmp, M_NEWNFSMNT); 1855 1856 /* Free up the delegation structures for forced dismounts. */ 1857 TAILQ_FOREACH_SAFE(dp, &dh, nfsdl_list, ndp) { 1858 TAILQ_REMOVE(&dh, dp, nfsdl_list); 1859 free(dp, M_NFSCLDELEG); 1860 } 1861 out: 1862 return (error); 1863 } 1864 1865 /* 1866 * Return root of a filesystem 1867 */ 1868 static int 1869 nfs_root(struct mount *mp, int flags, struct vnode **vpp) 1870 { 1871 struct vnode *vp; 1872 struct nfsmount *nmp; 1873 struct nfsnode *np; 1874 int error; 1875 1876 nmp = VFSTONFS(mp); 1877 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags); 1878 if (error) 1879 return error; 1880 vp = NFSTOV(np); 1881 /* 1882 * Get transfer parameters and attributes for root vnode once. 1883 */ 1884 mtx_lock(&nmp->nm_mtx); 1885 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) { 1886 mtx_unlock(&nmp->nm_mtx); 1887 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread); 1888 } else 1889 mtx_unlock(&nmp->nm_mtx); 1890 if (vp->v_type == VNON) 1891 vp->v_type = VDIR; 1892 vp->v_vflag |= VV_ROOT; 1893 *vpp = vp; 1894 return (0); 1895 } 1896 1897 /* 1898 * Flush out the buffer cache 1899 */ 1900 /* ARGSUSED */ 1901 static int 1902 nfs_sync(struct mount *mp, int waitfor) 1903 { 1904 struct vnode *vp, *mvp; 1905 struct thread *td; 1906 int error, allerror = 0; 1907 1908 td = curthread; 1909 1910 MNT_ILOCK(mp); 1911 /* 1912 * If a forced dismount is in progress, return from here so that 1913 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before 1914 * calling VFS_UNMOUNT(). 1915 */ 1916 if (NFSCL_FORCEDISM(mp)) { 1917 MNT_IUNLOCK(mp); 1918 return (EBADF); 1919 } 1920 MNT_IUNLOCK(mp); 1921 1922 /* 1923 * Force stale buffer cache information to be flushed. 1924 */ 1925 loop: 1926 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { 1927 /* XXX Racy bv_cnt check. */ 1928 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 || 1929 waitfor == MNT_LAZY) { 1930 VI_UNLOCK(vp); 1931 continue; 1932 } 1933 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) { 1934 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 1935 goto loop; 1936 } 1937 error = VOP_FSYNC(vp, waitfor, td); 1938 if (error) 1939 allerror = error; 1940 NFSVOPUNLOCK(vp); 1941 vrele(vp); 1942 } 1943 return (allerror); 1944 } 1945 1946 static int 1947 nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req) 1948 { 1949 struct nfsmount *nmp = VFSTONFS(mp); 1950 struct vfsquery vq; 1951 int error; 1952 1953 bzero(&vq, sizeof(vq)); 1954 switch (op) { 1955 #if 0 1956 case VFS_CTL_NOLOCKS: 1957 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0; 1958 if (req->oldptr != NULL) { 1959 error = SYSCTL_OUT(req, &val, sizeof(val)); 1960 if (error) 1961 return (error); 1962 } 1963 if (req->newptr != NULL) { 1964 error = SYSCTL_IN(req, &val, sizeof(val)); 1965 if (error) 1966 return (error); 1967 if (val) 1968 nmp->nm_flag |= NFSMNT_NOLOCKS; 1969 else 1970 nmp->nm_flag &= ~NFSMNT_NOLOCKS; 1971 } 1972 break; 1973 #endif 1974 case VFS_CTL_QUERY: 1975 mtx_lock(&nmp->nm_mtx); 1976 if (nmp->nm_state & NFSSTA_TIMEO) 1977 vq.vq_flags |= VQ_NOTRESP; 1978 mtx_unlock(&nmp->nm_mtx); 1979 #if 0 1980 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) && 1981 (nmp->nm_state & NFSSTA_LOCKTIMEO)) 1982 vq.vq_flags |= VQ_NOTRESPLOCK; 1983 #endif 1984 error = SYSCTL_OUT(req, &vq, sizeof(vq)); 1985 break; 1986 case VFS_CTL_TIMEO: 1987 if (req->oldptr != NULL) { 1988 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay, 1989 sizeof(nmp->nm_tprintf_initial_delay)); 1990 if (error) 1991 return (error); 1992 } 1993 if (req->newptr != NULL) { 1994 error = vfs_suser(mp, req->td); 1995 if (error) 1996 return (error); 1997 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay, 1998 sizeof(nmp->nm_tprintf_initial_delay)); 1999 if (error) 2000 return (error); 2001 if (nmp->nm_tprintf_initial_delay < 0) 2002 nmp->nm_tprintf_initial_delay = 0; 2003 } 2004 break; 2005 default: 2006 return (ENOTSUP); 2007 } 2008 return (0); 2009 } 2010 2011 /* 2012 * Purge any RPCs in progress, so that they will all return errors. 2013 * This allows dounmount() to continue as far as VFS_UNMOUNT() for a 2014 * forced dismount. 2015 */ 2016 static void 2017 nfs_purge(struct mount *mp) 2018 { 2019 struct nfsmount *nmp = VFSTONFS(mp); 2020 2021 newnfs_nmcancelreqs(nmp); 2022 } 2023 2024 /* 2025 * Extract the information needed by the nlm from the nfs vnode. 2026 */ 2027 static void 2028 nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp, 2029 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep, 2030 struct timeval *timeop) 2031 { 2032 struct nfsmount *nmp; 2033 struct nfsnode *np = VTONFS(vp); 2034 2035 nmp = VFSTONFS(vp->v_mount); 2036 if (fhlenp != NULL) 2037 *fhlenp = (size_t)np->n_fhp->nfh_len; 2038 if (fhp != NULL) 2039 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len); 2040 if (sp != NULL) 2041 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp))); 2042 if (is_v3p != NULL) 2043 *is_v3p = NFS_ISV3(vp); 2044 if (sizep != NULL) 2045 *sizep = np->n_size; 2046 if (timeop != NULL) { 2047 timeop->tv_sec = nmp->nm_timeo / NFS_HZ; 2048 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ); 2049 } 2050 } 2051 2052 /* 2053 * This function prints out an option name, based on the conditional 2054 * argument. 2055 */ 2056 static __inline void nfscl_printopt(struct nfsmount *nmp, int testval, 2057 char *opt, char **buf, size_t *blen) 2058 { 2059 int len; 2060 2061 if (testval != 0 && *blen > strlen(opt)) { 2062 len = snprintf(*buf, *blen, "%s", opt); 2063 if (len != strlen(opt)) 2064 printf("EEK!!\n"); 2065 *buf += len; 2066 *blen -= len; 2067 } 2068 } 2069 2070 /* 2071 * This function printf out an options integer value. 2072 */ 2073 static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval, 2074 char *opt, char **buf, size_t *blen) 2075 { 2076 int len; 2077 2078 if (*blen > strlen(opt) + 1) { 2079 /* Could result in truncated output string. */ 2080 len = snprintf(*buf, *blen, "%s=%d", opt, optval); 2081 if (len < *blen) { 2082 *buf += len; 2083 *blen -= len; 2084 } 2085 } 2086 } 2087 2088 /* 2089 * Load the option flags and values into the buffer. 2090 */ 2091 void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen) 2092 { 2093 char *buf; 2094 size_t blen; 2095 2096 buf = buffer; 2097 blen = buflen; 2098 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf, 2099 &blen); 2100 if ((nmp->nm_flag & NFSMNT_NFSV4) != 0) { 2101 nfscl_printoptval(nmp, nmp->nm_minorvers, ",minorversion", &buf, 2102 &blen); 2103 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_PNFS) != 0, ",pnfs", 2104 &buf, &blen); 2105 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_ONEOPENOWN) != 0 && 2106 nmp->nm_minorvers > 0, ",oneopenown", &buf, &blen); 2107 } 2108 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf, 2109 &blen); 2110 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0, 2111 "nfsv2", &buf, &blen); 2112 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen); 2113 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen); 2114 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport", 2115 &buf, &blen); 2116 nfscl_printopt(nmp, (nmp->nm_newflag & NFSMNT_TLS) != 0, ",tls", &buf, 2117 &blen); 2118 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn", 2119 &buf, &blen); 2120 nfscl_printoptval(nmp, nmp->nm_aconnect + 1, ",nconnect", &buf, &blen); 2121 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf, 2122 &blen); 2123 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf, 2124 &blen); 2125 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf, 2126 &blen); 2127 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf, 2128 &blen); 2129 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf, 2130 &blen); 2131 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NONCONTIGWR) != 0, 2132 ",noncontigwr", &buf, &blen); 2133 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) == 2134 0, ",lockd", &buf, &blen); 2135 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) == 2136 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen); 2137 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus", 2138 &buf, &blen); 2139 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys", 2140 &buf, &blen); 2141 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 2142 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen); 2143 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 2144 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i", 2145 &buf, &blen); 2146 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 2147 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p", 2148 &buf, &blen); 2149 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen); 2150 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen); 2151 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen); 2152 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen); 2153 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen); 2154 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf, 2155 &blen); 2156 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen); 2157 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen); 2158 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf, 2159 &blen); 2160 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen); 2161 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf, 2162 &blen); 2163 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen); 2164 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen); 2165 } 2166