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