nfs_clvfsops.c revision 244289
1/*- 2 * Copyright (c) 1989, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * from nfs_vfsops.c 8.12 (Berkeley) 5/20/95 33 */ 34 35#include <sys/cdefs.h> 36__FBSDID("$FreeBSD: stable/9/sys/fs/nfsclient/nfs_clvfsops.c 244289 2012-12-16 14:01:56Z rmacklem $"); 37 38 39#include "opt_bootp.h" 40#include "opt_nfsroot.h" 41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/kernel.h> 45#include <sys/bio.h> 46#include <sys/buf.h> 47#include <sys/clock.h> 48#include <sys/jail.h> 49#include <sys/limits.h> 50#include <sys/lock.h> 51#include <sys/malloc.h> 52#include <sys/mbuf.h> 53#include <sys/module.h> 54#include <sys/mount.h> 55#include <sys/proc.h> 56#include <sys/socket.h> 57#include <sys/socketvar.h> 58#include <sys/sockio.h> 59#include <sys/sysctl.h> 60#include <sys/vnode.h> 61#include <sys/signalvar.h> 62 63#include <vm/vm.h> 64#include <vm/vm_extern.h> 65#include <vm/uma.h> 66 67#include <net/if.h> 68#include <net/route.h> 69#include <netinet/in.h> 70 71#include <fs/nfs/nfsport.h> 72#include <fs/nfsclient/nfsnode.h> 73#include <fs/nfsclient/nfsmount.h> 74#include <fs/nfsclient/nfs.h> 75#include <nfs/nfsdiskless.h> 76 77FEATURE(nfscl, "NFSv4 client"); 78 79extern int nfscl_ticks; 80extern struct timeval nfsboottime; 81extern struct nfsstats newnfsstats; 82extern int nfsrv_useacl; 83 84MALLOC_DEFINE(M_NEWNFSREQ, "newnfsclient_req", "New NFS request header"); 85MALLOC_DEFINE(M_NEWNFSMNT, "newnfsmnt", "New NFS mount struct"); 86 87SYSCTL_DECL(_vfs_nfs); 88static int nfs_ip_paranoia = 1; 89SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_ip_paranoia, CTLFLAG_RW, 90 &nfs_ip_paranoia, 0, ""); 91static int nfs_tprintf_initial_delay = NFS_TPRINTF_INITIAL_DELAY; 92SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_INITIAL_DELAY, 93 downdelayinitial, CTLFLAG_RW, &nfs_tprintf_initial_delay, 0, ""); 94/* how long between console messages "nfs server foo not responding" */ 95static int nfs_tprintf_delay = NFS_TPRINTF_DELAY; 96SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY, 97 downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, ""); 98 99static int nfs_mountroot(struct mount *); 100static void nfs_sec_name(char *, int *); 101static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, 102 struct nfs_args *argp, const char *, struct ucred *, 103 struct thread *); 104static int mountnfs(struct nfs_args *, struct mount *, 105 struct sockaddr *, char *, u_char *, int, u_char *, int, 106 u_char *, int, struct vnode **, struct ucred *, 107 struct thread *, int, int); 108static void nfs_getnlminfo(struct vnode *, uint8_t *, size_t *, 109 struct sockaddr_storage *, int *, off_t *, 110 struct timeval *); 111static vfs_mount_t nfs_mount; 112static vfs_cmount_t nfs_cmount; 113static vfs_unmount_t nfs_unmount; 114static vfs_root_t nfs_root; 115static vfs_statfs_t nfs_statfs; 116static vfs_sync_t nfs_sync; 117static vfs_sysctl_t nfs_sysctl; 118 119/* 120 * nfs vfs operations. 121 */ 122static struct vfsops nfs_vfsops = { 123 .vfs_init = ncl_init, 124 .vfs_mount = nfs_mount, 125 .vfs_cmount = nfs_cmount, 126 .vfs_root = nfs_root, 127 .vfs_statfs = nfs_statfs, 128 .vfs_sync = nfs_sync, 129 .vfs_uninit = ncl_uninit, 130 .vfs_unmount = nfs_unmount, 131 .vfs_sysctl = nfs_sysctl, 132}; 133VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK); 134 135/* So that loader and kldload(2) can find us, wherever we are.. */ 136MODULE_VERSION(nfs, 1); 137MODULE_DEPEND(nfs, nfscommon, 1, 1, 1); 138MODULE_DEPEND(nfs, krpc, 1, 1, 1); 139MODULE_DEPEND(nfs, nfssvc, 1, 1, 1); 140MODULE_DEPEND(nfs, nfslock, 1, 1, 1); 141 142/* 143 * This structure is now defined in sys/nfs/nfs_diskless.c so that it 144 * can be shared by both NFS clients. It is declared here so that it 145 * will be defined for kernels built without NFS_ROOT, although it 146 * isn't used in that case. 147 */ 148#if !defined(NFS_ROOT) && !defined(NFSCLIENT) 149struct nfs_diskless nfs_diskless = { { { 0 } } }; 150struct nfsv3_diskless nfsv3_diskless = { { { 0 } } }; 151int nfs_diskless_valid = 0; 152#endif 153 154SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, 155 &nfs_diskless_valid, 0, 156 "Has the diskless struct been filled correctly"); 157 158SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, 159 nfsv3_diskless.root_hostnam, 0, "Path to nfs root"); 160 161SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, 162 &nfsv3_diskless.root_saddr, sizeof(nfsv3_diskless.root_saddr), 163 "%Ssockaddr_in", "Diskless root nfs address"); 164 165 166void newnfsargs_ntoh(struct nfs_args *); 167static int nfs_mountdiskless(char *, 168 struct sockaddr_in *, struct nfs_args *, 169 struct thread *, struct vnode **, struct mount *); 170static void nfs_convert_diskless(void); 171static void nfs_convert_oargs(struct nfs_args *args, 172 struct onfs_args *oargs); 173 174int 175newnfs_iosize(struct nfsmount *nmp) 176{ 177 int iosize, maxio; 178 179 /* First, set the upper limit for iosize */ 180 if (nmp->nm_flag & NFSMNT_NFSV4) { 181 maxio = NFS_MAXBSIZE; 182 } else if (nmp->nm_flag & NFSMNT_NFSV3) { 183 if (nmp->nm_sotype == SOCK_DGRAM) 184 maxio = NFS_MAXDGRAMDATA; 185 else 186 maxio = NFS_MAXBSIZE; 187 } else { 188 maxio = NFS_V2MAXDATA; 189 } 190 if (nmp->nm_rsize > maxio || nmp->nm_rsize == 0) 191 nmp->nm_rsize = maxio; 192 if (nmp->nm_rsize > MAXBSIZE) 193 nmp->nm_rsize = MAXBSIZE; 194 if (nmp->nm_readdirsize > maxio || nmp->nm_readdirsize == 0) 195 nmp->nm_readdirsize = maxio; 196 if (nmp->nm_readdirsize > nmp->nm_rsize) 197 nmp->nm_readdirsize = nmp->nm_rsize; 198 if (nmp->nm_wsize > maxio || nmp->nm_wsize == 0) 199 nmp->nm_wsize = maxio; 200 if (nmp->nm_wsize > MAXBSIZE) 201 nmp->nm_wsize = MAXBSIZE; 202 203 /* 204 * Calculate the size used for io buffers. Use the larger 205 * of the two sizes to minimise nfs requests but make sure 206 * that it is at least one VM page to avoid wasting buffer 207 * space. 208 */ 209 iosize = imax(nmp->nm_rsize, nmp->nm_wsize); 210 iosize = imax(iosize, PAGE_SIZE); 211 nmp->nm_mountp->mnt_stat.f_iosize = iosize; 212 return (iosize); 213} 214 215static void 216nfs_convert_oargs(struct nfs_args *args, struct onfs_args *oargs) 217{ 218 219 args->version = NFS_ARGSVERSION; 220 args->addr = oargs->addr; 221 args->addrlen = oargs->addrlen; 222 args->sotype = oargs->sotype; 223 args->proto = oargs->proto; 224 args->fh = oargs->fh; 225 args->fhsize = oargs->fhsize; 226 args->flags = oargs->flags; 227 args->wsize = oargs->wsize; 228 args->rsize = oargs->rsize; 229 args->readdirsize = oargs->readdirsize; 230 args->timeo = oargs->timeo; 231 args->retrans = oargs->retrans; 232 args->readahead = oargs->readahead; 233 args->hostname = oargs->hostname; 234} 235 236static void 237nfs_convert_diskless(void) 238{ 239 240 bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, 241 sizeof(struct ifaliasreq)); 242 bcopy(&nfs_diskless.mygateway, &nfsv3_diskless.mygateway, 243 sizeof(struct sockaddr_in)); 244 nfs_convert_oargs(&nfsv3_diskless.root_args,&nfs_diskless.root_args); 245 if (nfsv3_diskless.root_args.flags & NFSMNT_NFSV3) { 246 nfsv3_diskless.root_fhsize = NFSX_MYFH; 247 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_MYFH); 248 } else { 249 nfsv3_diskless.root_fhsize = NFSX_V2FH; 250 bcopy(nfs_diskless.root_fh, nfsv3_diskless.root_fh, NFSX_V2FH); 251 } 252 bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, 253 sizeof(struct sockaddr_in)); 254 bcopy(nfs_diskless.root_hostnam, nfsv3_diskless.root_hostnam, MNAMELEN); 255 nfsv3_diskless.root_time = nfs_diskless.root_time; 256 bcopy(nfs_diskless.my_hostnam, nfsv3_diskless.my_hostnam, 257 MAXHOSTNAMELEN); 258 nfs_diskless_valid = 3; 259} 260 261/* 262 * nfs statfs call 263 */ 264static int 265nfs_statfs(struct mount *mp, struct statfs *sbp) 266{ 267 struct vnode *vp; 268 struct thread *td; 269 struct nfsmount *nmp = VFSTONFS(mp); 270 struct nfsvattr nfsva; 271 struct nfsfsinfo fs; 272 struct nfsstatfs sb; 273 int error = 0, attrflag, gotfsinfo = 0, ret; 274 struct nfsnode *np; 275 276 td = curthread; 277 278 error = vfs_busy(mp, MBF_NOWAIT); 279 if (error) 280 return (error); 281 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, LK_EXCLUSIVE); 282 if (error) { 283 vfs_unbusy(mp); 284 return (error); 285 } 286 vp = NFSTOV(np); 287 mtx_lock(&nmp->nm_mtx); 288 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) { 289 mtx_unlock(&nmp->nm_mtx); 290 error = nfsrpc_fsinfo(vp, &fs, td->td_ucred, td, &nfsva, 291 &attrflag, NULL); 292 if (!error) 293 gotfsinfo = 1; 294 } else 295 mtx_unlock(&nmp->nm_mtx); 296 if (!error) 297 error = nfsrpc_statfs(vp, &sb, &fs, td->td_ucred, td, &nfsva, 298 &attrflag, NULL); 299 if (attrflag == 0) { 300 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1, 301 td->td_ucred, td, &nfsva, NULL); 302 if (ret) { 303 /* 304 * Just set default values to get things going. 305 */ 306 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr)); 307 nfsva.na_vattr.va_type = VDIR; 308 nfsva.na_vattr.va_mode = 0777; 309 nfsva.na_vattr.va_nlink = 100; 310 nfsva.na_vattr.va_uid = (uid_t)0; 311 nfsva.na_vattr.va_gid = (gid_t)0; 312 nfsva.na_vattr.va_fileid = 2; 313 nfsva.na_vattr.va_gen = 1; 314 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE; 315 nfsva.na_vattr.va_size = 512 * 1024; 316 } 317 } 318 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 319 if (!error) { 320 mtx_lock(&nmp->nm_mtx); 321 if (gotfsinfo || (nmp->nm_flag & NFSMNT_NFSV4)) 322 nfscl_loadfsinfo(nmp, &fs); 323 nfscl_loadsbinfo(nmp, &sb, sbp); 324 sbp->f_iosize = newnfs_iosize(nmp); 325 mtx_unlock(&nmp->nm_mtx); 326 if (sbp != &mp->mnt_stat) { 327 bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); 328 bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); 329 } 330 strncpy(&sbp->f_fstypename[0], mp->mnt_vfc->vfc_name, MFSNAMELEN); 331 } else if (NFS_ISV4(vp)) { 332 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 333 } 334 vput(vp); 335 vfs_unbusy(mp); 336 return (error); 337} 338 339/* 340 * nfs version 3 fsinfo rpc call 341 */ 342int 343ncl_fsinfo(struct nfsmount *nmp, struct vnode *vp, struct ucred *cred, 344 struct thread *td) 345{ 346 struct nfsfsinfo fs; 347 struct nfsvattr nfsva; 348 int error, attrflag; 349 350 error = nfsrpc_fsinfo(vp, &fs, cred, td, &nfsva, &attrflag, NULL); 351 if (!error) { 352 if (attrflag) 353 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 354 1); 355 mtx_lock(&nmp->nm_mtx); 356 nfscl_loadfsinfo(nmp, &fs); 357 mtx_unlock(&nmp->nm_mtx); 358 } 359 return (error); 360} 361 362/* 363 * Mount a remote root fs via. nfs. This depends on the info in the 364 * nfs_diskless structure that has been filled in properly by some primary 365 * bootstrap. 366 * It goes something like this: 367 * - do enough of "ifconfig" by calling ifioctl() so that the system 368 * can talk to the server 369 * - If nfs_diskless.mygateway is filled in, use that address as 370 * a default gateway. 371 * - build the rootfs mount point and call mountnfs() to do the rest. 372 * 373 * It is assumed to be safe to read, modify, and write the nfsv3_diskless 374 * structure, as well as other global NFS client variables here, as 375 * nfs_mountroot() will be called once in the boot before any other NFS 376 * client activity occurs. 377 */ 378static int 379nfs_mountroot(struct mount *mp) 380{ 381 struct thread *td = curthread; 382 struct nfsv3_diskless *nd = &nfsv3_diskless; 383 struct socket *so; 384 struct vnode *vp; 385 struct ifreq ir; 386 int error; 387 u_long l; 388 char buf[128]; 389 char *cp; 390 391#if defined(BOOTP_NFSROOT) && defined(BOOTP) 392 bootpc_init(); /* use bootp to get nfs_diskless filled in */ 393#elif defined(NFS_ROOT) 394 nfs_setup_diskless(); 395#endif 396 397 if (nfs_diskless_valid == 0) 398 return (-1); 399 if (nfs_diskless_valid == 1) 400 nfs_convert_diskless(); 401 402 /* 403 * XXX splnet, so networks will receive... 404 */ 405 splnet(); 406 407 /* 408 * Do enough of ifconfig(8) so that the critical net interface can 409 * talk to the server. 410 */ 411 error = socreate(nd->myif.ifra_addr.sa_family, &so, nd->root_args.sotype, 0, 412 td->td_ucred, td); 413 if (error) 414 panic("nfs_mountroot: socreate(%04x): %d", 415 nd->myif.ifra_addr.sa_family, error); 416 417#if 0 /* XXX Bad idea */ 418 /* 419 * We might not have been told the right interface, so we pass 420 * over the first ten interfaces of the same kind, until we get 421 * one of them configured. 422 */ 423 424 for (i = strlen(nd->myif.ifra_name) - 1; 425 nd->myif.ifra_name[i] >= '0' && 426 nd->myif.ifra_name[i] <= '9'; 427 nd->myif.ifra_name[i] ++) { 428 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td); 429 if(!error) 430 break; 431 } 432#endif 433 error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, td); 434 if (error) 435 panic("nfs_mountroot: SIOCAIFADDR: %d", error); 436 if ((cp = getenv("boot.netif.mtu")) != NULL) { 437 ir.ifr_mtu = strtol(cp, NULL, 10); 438 bcopy(nd->myif.ifra_name, ir.ifr_name, IFNAMSIZ); 439 freeenv(cp); 440 error = ifioctl(so, SIOCSIFMTU, (caddr_t)&ir, td); 441 if (error) 442 printf("nfs_mountroot: SIOCSIFMTU: %d", error); 443 } 444 soclose(so); 445 446 /* 447 * If the gateway field is filled in, set it as the default route. 448 * Note that pxeboot will set a default route of 0 if the route 449 * is not set by the DHCP server. Check also for a value of 0 450 * to avoid panicking inappropriately in that situation. 451 */ 452 if (nd->mygateway.sin_len != 0 && 453 nd->mygateway.sin_addr.s_addr != 0) { 454 struct sockaddr_in mask, sin; 455 456 bzero((caddr_t)&mask, sizeof(mask)); 457 sin = mask; 458 sin.sin_family = AF_INET; 459 sin.sin_len = sizeof(sin); 460 /* XXX MRT use table 0 for this sort of thing */ 461 CURVNET_SET(TD_TO_VNET(td)); 462 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&sin, 463 (struct sockaddr *)&nd->mygateway, 464 (struct sockaddr *)&mask, 465 RTF_UP | RTF_GATEWAY, NULL, RT_DEFAULT_FIB); 466 CURVNET_RESTORE(); 467 if (error) 468 panic("nfs_mountroot: RTM_ADD: %d", error); 469 } 470 471 /* 472 * Create the rootfs mount point. 473 */ 474 nd->root_args.fh = nd->root_fh; 475 nd->root_args.fhsize = nd->root_fhsize; 476 l = ntohl(nd->root_saddr.sin_addr.s_addr); 477 snprintf(buf, sizeof(buf), "%ld.%ld.%ld.%ld:%s", 478 (l >> 24) & 0xff, (l >> 16) & 0xff, 479 (l >> 8) & 0xff, (l >> 0) & 0xff, nd->root_hostnam); 480 printf("NFS ROOT: %s\n", buf); 481 nd->root_args.hostname = buf; 482 if ((error = nfs_mountdiskless(buf, 483 &nd->root_saddr, &nd->root_args, td, &vp, mp)) != 0) { 484 return (error); 485 } 486 487 /* 488 * This is not really an nfs issue, but it is much easier to 489 * set hostname here and then let the "/etc/rc.xxx" files 490 * mount the right /var based upon its preset value. 491 */ 492 mtx_lock(&prison0.pr_mtx); 493 strlcpy(prison0.pr_hostname, nd->my_hostnam, 494 sizeof(prison0.pr_hostname)); 495 mtx_unlock(&prison0.pr_mtx); 496 inittodr(ntohl(nd->root_time)); 497 return (0); 498} 499 500/* 501 * Internal version of mount system call for diskless setup. 502 */ 503static int 504nfs_mountdiskless(char *path, 505 struct sockaddr_in *sin, struct nfs_args *args, struct thread *td, 506 struct vnode **vpp, struct mount *mp) 507{ 508 struct sockaddr *nam; 509 int dirlen, error; 510 char *dirpath; 511 512 /* 513 * Find the directory path in "path", which also has the server's 514 * name/ip address in it. 515 */ 516 dirpath = strchr(path, ':'); 517 if (dirpath != NULL) 518 dirlen = strlen(++dirpath); 519 else 520 dirlen = 0; 521 nam = sodupsockaddr((struct sockaddr *)sin, M_WAITOK); 522 if ((error = mountnfs(args, mp, nam, path, NULL, 0, dirpath, dirlen, 523 NULL, 0, vpp, td->td_ucred, td, NFS_DEFAULT_NAMETIMEO, 524 NFS_DEFAULT_NEGNAMETIMEO)) != 0) { 525 printf("nfs_mountroot: mount %s on /: %d\n", path, error); 526 return (error); 527 } 528 return (0); 529} 530 531static void 532nfs_sec_name(char *sec, int *flagsp) 533{ 534 if (!strcmp(sec, "krb5")) 535 *flagsp |= NFSMNT_KERB; 536 else if (!strcmp(sec, "krb5i")) 537 *flagsp |= (NFSMNT_KERB | NFSMNT_INTEGRITY); 538 else if (!strcmp(sec, "krb5p")) 539 *flagsp |= (NFSMNT_KERB | NFSMNT_PRIVACY); 540} 541 542static void 543nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp, 544 const char *hostname, struct ucred *cred, struct thread *td) 545{ 546 int s; 547 int adjsock; 548 char *p; 549 550 s = splnet(); 551 552 /* 553 * Set read-only flag if requested; otherwise, clear it if this is 554 * an update. If this is not an update, then either the read-only 555 * flag is already clear, or this is a root mount and it was set 556 * intentionally at some previous point. 557 */ 558 if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL) == 0) { 559 MNT_ILOCK(mp); 560 mp->mnt_flag |= MNT_RDONLY; 561 MNT_IUNLOCK(mp); 562 } else if (mp->mnt_flag & MNT_UPDATE) { 563 MNT_ILOCK(mp); 564 mp->mnt_flag &= ~MNT_RDONLY; 565 MNT_IUNLOCK(mp); 566 } 567 568 /* 569 * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes 570 * no sense in that context. Also, set up appropriate retransmit 571 * and soft timeout behavior. 572 */ 573 if (argp->sotype == SOCK_STREAM) { 574 nmp->nm_flag &= ~NFSMNT_NOCONN; 575 nmp->nm_timeo = NFS_MAXTIMEO; 576 if ((argp->flags & NFSMNT_NFSV4) != 0) 577 nmp->nm_retry = INT_MAX; 578 else 579 nmp->nm_retry = NFS_RETRANS_TCP; 580 } 581 582 /* Also clear RDIRPLUS if NFSv2, it crashes some servers */ 583 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) { 584 argp->flags &= ~NFSMNT_RDIRPLUS; 585 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 586 } 587 588 /* Clear NFSMNT_RESVPORT for NFSv4, since it is not required. */ 589 if ((argp->flags & NFSMNT_NFSV4) != 0) { 590 argp->flags &= ~NFSMNT_RESVPORT; 591 nmp->nm_flag &= ~NFSMNT_RESVPORT; 592 } 593 594 /* Re-bind if rsrvd port requested and wasn't on one */ 595 adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) 596 && (argp->flags & NFSMNT_RESVPORT); 597 /* Also re-bind if we're switching to/from a connected UDP socket */ 598 adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != 599 (argp->flags & NFSMNT_NOCONN)); 600 601 /* Update flags atomically. Don't change the lock bits. */ 602 nmp->nm_flag = argp->flags | nmp->nm_flag; 603 splx(s); 604 605 if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { 606 nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; 607 if (nmp->nm_timeo < NFS_MINTIMEO) 608 nmp->nm_timeo = NFS_MINTIMEO; 609 else if (nmp->nm_timeo > NFS_MAXTIMEO) 610 nmp->nm_timeo = NFS_MAXTIMEO; 611 } 612 613 if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { 614 nmp->nm_retry = argp->retrans; 615 if (nmp->nm_retry > NFS_MAXREXMIT) 616 nmp->nm_retry = NFS_MAXREXMIT; 617 } 618 619 if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { 620 nmp->nm_wsize = argp->wsize; 621 /* Round down to multiple of blocksize */ 622 nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); 623 if (nmp->nm_wsize <= 0) 624 nmp->nm_wsize = NFS_FABLKSIZE; 625 } 626 627 if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { 628 nmp->nm_rsize = argp->rsize; 629 /* Round down to multiple of blocksize */ 630 nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); 631 if (nmp->nm_rsize <= 0) 632 nmp->nm_rsize = NFS_FABLKSIZE; 633 } 634 635 if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { 636 nmp->nm_readdirsize = argp->readdirsize; 637 } 638 639 if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) 640 nmp->nm_acregmin = argp->acregmin; 641 else 642 nmp->nm_acregmin = NFS_MINATTRTIMO; 643 if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) 644 nmp->nm_acregmax = argp->acregmax; 645 else 646 nmp->nm_acregmax = NFS_MAXATTRTIMO; 647 if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) 648 nmp->nm_acdirmin = argp->acdirmin; 649 else 650 nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; 651 if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) 652 nmp->nm_acdirmax = argp->acdirmax; 653 else 654 nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; 655 if (nmp->nm_acdirmin > nmp->nm_acdirmax) 656 nmp->nm_acdirmin = nmp->nm_acdirmax; 657 if (nmp->nm_acregmin > nmp->nm_acregmax) 658 nmp->nm_acregmin = nmp->nm_acregmax; 659 660 if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0) { 661 if (argp->readahead <= NFS_MAXRAHEAD) 662 nmp->nm_readahead = argp->readahead; 663 else 664 nmp->nm_readahead = NFS_MAXRAHEAD; 665 } 666 if ((argp->flags & NFSMNT_WCOMMITSIZE) && argp->wcommitsize >= 0) { 667 if (argp->wcommitsize < nmp->nm_wsize) 668 nmp->nm_wcommitsize = nmp->nm_wsize; 669 else 670 nmp->nm_wcommitsize = argp->wcommitsize; 671 } 672 673 adjsock |= ((nmp->nm_sotype != argp->sotype) || 674 (nmp->nm_soproto != argp->proto)); 675 676 if (nmp->nm_client != NULL && adjsock) { 677 int haslock = 0, error = 0; 678 679 if (nmp->nm_sotype == SOCK_STREAM) { 680 error = newnfs_sndlock(&nmp->nm_sockreq.nr_lock); 681 if (!error) 682 haslock = 1; 683 } 684 if (!error) { 685 newnfs_disconnect(&nmp->nm_sockreq); 686 if (haslock) 687 newnfs_sndunlock(&nmp->nm_sockreq.nr_lock); 688 nmp->nm_sotype = argp->sotype; 689 nmp->nm_soproto = argp->proto; 690 if (nmp->nm_sotype == SOCK_DGRAM) 691 while (newnfs_connect(nmp, &nmp->nm_sockreq, 692 cred, td, 0)) { 693 printf("newnfs_args: retrying connect\n"); 694 (void) nfs_catnap(PSOCK, 0, "newnfscon"); 695 } 696 } 697 } else { 698 nmp->nm_sotype = argp->sotype; 699 nmp->nm_soproto = argp->proto; 700 } 701 702 if (hostname != NULL) { 703 strlcpy(nmp->nm_hostname, hostname, 704 sizeof(nmp->nm_hostname)); 705 p = strchr(nmp->nm_hostname, ':'); 706 if (p != NULL) 707 *p = '\0'; 708 } 709} 710 711static const char *nfs_opts[] = { "from", "nfs_args", 712 "noatime", "noexec", "suiddir", "nosuid", "nosymfollow", "union", 713 "noclusterr", "noclusterw", "multilabel", "acls", "force", "update", 714 "async", "noconn", "nolockd", "conn", "lockd", "intr", "rdirplus", 715 "readdirsize", "soft", "hard", "mntudp", "tcp", "udp", "wsize", "rsize", 716 "retrans", "acregmin", "acregmax", "acdirmin", "acdirmax", "resvport", 717 "readahead", "hostname", "timeout", "addr", "fh", "nfsv3", "sec", 718 "principal", "nfsv4", "gssname", "allgssname", "dirpath", 719 "nametimeo", "negnametimeo", "nocto", "wcommitsize", 720 NULL }; 721 722/* 723 * VFS Operations. 724 * 725 * mount system call 726 * It seems a bit dumb to copyinstr() the host and path here and then 727 * bcopy() them in mountnfs(), but I wanted to detect errors before 728 * doing the sockargs() call because sockargs() allocates an mbuf and 729 * an error after that means that I have to release the mbuf. 730 */ 731/* ARGSUSED */ 732static int 733nfs_mount(struct mount *mp) 734{ 735 struct nfs_args args = { 736 .version = NFS_ARGSVERSION, 737 .addr = NULL, 738 .addrlen = sizeof (struct sockaddr_in), 739 .sotype = SOCK_STREAM, 740 .proto = 0, 741 .fh = NULL, 742 .fhsize = 0, 743 .flags = NFSMNT_RESVPORT, 744 .wsize = NFS_WSIZE, 745 .rsize = NFS_RSIZE, 746 .readdirsize = NFS_READDIRSIZE, 747 .timeo = 10, 748 .retrans = NFS_RETRANS, 749 .readahead = NFS_DEFRAHEAD, 750 .wcommitsize = 0, /* was: NQ_DEFLEASE */ 751 .hostname = NULL, 752 .acregmin = NFS_MINATTRTIMO, 753 .acregmax = NFS_MAXATTRTIMO, 754 .acdirmin = NFS_MINDIRATTRTIMO, 755 .acdirmax = NFS_MAXDIRATTRTIMO, 756 }; 757 int error = 0, ret, len; 758 struct sockaddr *nam = NULL; 759 struct vnode *vp; 760 struct thread *td; 761 char hst[MNAMELEN]; 762 u_char nfh[NFSX_FHMAX], krbname[100], dirpath[100], srvkrbname[100]; 763 char *opt, *name, *secname; 764 int nametimeo = NFS_DEFAULT_NAMETIMEO; 765 int negnametimeo = NFS_DEFAULT_NEGNAMETIMEO; 766 int dirlen, has_nfs_args_opt, krbnamelen, srvkrbnamelen; 767 size_t hstlen; 768 769 has_nfs_args_opt = 0; 770 if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) { 771 error = EINVAL; 772 goto out; 773 } 774 775 td = curthread; 776 if ((mp->mnt_flag & (MNT_ROOTFS | MNT_UPDATE)) == MNT_ROOTFS) { 777 error = nfs_mountroot(mp); 778 goto out; 779 } 780 781 nfscl_init(); 782 783 /* 784 * The old mount_nfs program passed the struct nfs_args 785 * from userspace to kernel. The new mount_nfs program 786 * passes string options via nmount() from userspace to kernel 787 * and we populate the struct nfs_args in the kernel. 788 */ 789 if (vfs_getopt(mp->mnt_optnew, "nfs_args", NULL, NULL) == 0) { 790 error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, 791 sizeof(args)); 792 if (error != 0) 793 goto out; 794 795 if (args.version != NFS_ARGSVERSION) { 796 error = EPROGMISMATCH; 797 goto out; 798 } 799 has_nfs_args_opt = 1; 800 } 801 802 /* Handle the new style options. */ 803 if (vfs_getopt(mp->mnt_optnew, "noconn", NULL, NULL) == 0) 804 args.flags |= NFSMNT_NOCONN; 805 if (vfs_getopt(mp->mnt_optnew, "conn", NULL, NULL) == 0) 806 args.flags |= NFSMNT_NOCONN; 807 if (vfs_getopt(mp->mnt_optnew, "nolockd", NULL, NULL) == 0) 808 args.flags |= NFSMNT_NOLOCKD; 809 if (vfs_getopt(mp->mnt_optnew, "lockd", NULL, NULL) == 0) 810 args.flags &= ~NFSMNT_NOLOCKD; 811 if (vfs_getopt(mp->mnt_optnew, "intr", NULL, NULL) == 0) 812 args.flags |= NFSMNT_INT; 813 if (vfs_getopt(mp->mnt_optnew, "rdirplus", NULL, NULL) == 0) 814 args.flags |= NFSMNT_RDIRPLUS; 815 if (vfs_getopt(mp->mnt_optnew, "resvport", NULL, NULL) == 0) 816 args.flags |= NFSMNT_RESVPORT; 817 if (vfs_getopt(mp->mnt_optnew, "noresvport", NULL, NULL) == 0) 818 args.flags &= ~NFSMNT_RESVPORT; 819 if (vfs_getopt(mp->mnt_optnew, "soft", NULL, NULL) == 0) 820 args.flags |= NFSMNT_SOFT; 821 if (vfs_getopt(mp->mnt_optnew, "hard", NULL, NULL) == 0) 822 args.flags &= ~NFSMNT_SOFT; 823 if (vfs_getopt(mp->mnt_optnew, "mntudp", NULL, NULL) == 0) 824 args.sotype = SOCK_DGRAM; 825 if (vfs_getopt(mp->mnt_optnew, "udp", NULL, NULL) == 0) 826 args.sotype = SOCK_DGRAM; 827 if (vfs_getopt(mp->mnt_optnew, "tcp", NULL, NULL) == 0) 828 args.sotype = SOCK_STREAM; 829 if (vfs_getopt(mp->mnt_optnew, "nfsv3", NULL, NULL) == 0) 830 args.flags |= NFSMNT_NFSV3; 831 if (vfs_getopt(mp->mnt_optnew, "nfsv4", NULL, NULL) == 0) { 832 args.flags |= NFSMNT_NFSV4; 833 args.sotype = SOCK_STREAM; 834 } 835 if (vfs_getopt(mp->mnt_optnew, "allgssname", NULL, NULL) == 0) 836 args.flags |= NFSMNT_ALLGSSNAME; 837 if (vfs_getopt(mp->mnt_optnew, "nocto", NULL, NULL) == 0) 838 args.flags |= NFSMNT_NOCTO; 839 if (vfs_getopt(mp->mnt_optnew, "readdirsize", (void **)&opt, NULL) == 0) { 840 if (opt == NULL) { 841 vfs_mount_error(mp, "illegal readdirsize"); 842 error = EINVAL; 843 goto out; 844 } 845 ret = sscanf(opt, "%d", &args.readdirsize); 846 if (ret != 1 || args.readdirsize <= 0) { 847 vfs_mount_error(mp, "illegal readdirsize: %s", 848 opt); 849 error = EINVAL; 850 goto out; 851 } 852 args.flags |= NFSMNT_READDIRSIZE; 853 } 854 if (vfs_getopt(mp->mnt_optnew, "readahead", (void **)&opt, NULL) == 0) { 855 if (opt == NULL) { 856 vfs_mount_error(mp, "illegal readahead"); 857 error = EINVAL; 858 goto out; 859 } 860 ret = sscanf(opt, "%d", &args.readahead); 861 if (ret != 1 || args.readahead <= 0) { 862 vfs_mount_error(mp, "illegal readahead: %s", 863 opt); 864 error = EINVAL; 865 goto out; 866 } 867 args.flags |= NFSMNT_READAHEAD; 868 } 869 if (vfs_getopt(mp->mnt_optnew, "wsize", (void **)&opt, NULL) == 0) { 870 if (opt == NULL) { 871 vfs_mount_error(mp, "illegal wsize"); 872 error = EINVAL; 873 goto out; 874 } 875 ret = sscanf(opt, "%d", &args.wsize); 876 if (ret != 1 || args.wsize <= 0) { 877 vfs_mount_error(mp, "illegal wsize: %s", 878 opt); 879 error = EINVAL; 880 goto out; 881 } 882 args.flags |= NFSMNT_WSIZE; 883 } 884 if (vfs_getopt(mp->mnt_optnew, "rsize", (void **)&opt, NULL) == 0) { 885 if (opt == NULL) { 886 vfs_mount_error(mp, "illegal rsize"); 887 error = EINVAL; 888 goto out; 889 } 890 ret = sscanf(opt, "%d", &args.rsize); 891 if (ret != 1 || args.rsize <= 0) { 892 vfs_mount_error(mp, "illegal wsize: %s", 893 opt); 894 error = EINVAL; 895 goto out; 896 } 897 args.flags |= NFSMNT_RSIZE; 898 } 899 if (vfs_getopt(mp->mnt_optnew, "retrans", (void **)&opt, NULL) == 0) { 900 if (opt == NULL) { 901 vfs_mount_error(mp, "illegal retrans"); 902 error = EINVAL; 903 goto out; 904 } 905 ret = sscanf(opt, "%d", &args.retrans); 906 if (ret != 1 || args.retrans <= 0) { 907 vfs_mount_error(mp, "illegal retrans: %s", 908 opt); 909 error = EINVAL; 910 goto out; 911 } 912 args.flags |= NFSMNT_RETRANS; 913 } 914 if (vfs_getopt(mp->mnt_optnew, "acregmin", (void **)&opt, NULL) == 0) { 915 ret = sscanf(opt, "%d", &args.acregmin); 916 if (ret != 1 || args.acregmin < 0) { 917 vfs_mount_error(mp, "illegal acregmin: %s", 918 opt); 919 error = EINVAL; 920 goto out; 921 } 922 args.flags |= NFSMNT_ACREGMIN; 923 } 924 if (vfs_getopt(mp->mnt_optnew, "acregmax", (void **)&opt, NULL) == 0) { 925 ret = sscanf(opt, "%d", &args.acregmax); 926 if (ret != 1 || args.acregmax < 0) { 927 vfs_mount_error(mp, "illegal acregmax: %s", 928 opt); 929 error = EINVAL; 930 goto out; 931 } 932 args.flags |= NFSMNT_ACREGMAX; 933 } 934 if (vfs_getopt(mp->mnt_optnew, "acdirmin", (void **)&opt, NULL) == 0) { 935 ret = sscanf(opt, "%d", &args.acdirmin); 936 if (ret != 1 || args.acdirmin < 0) { 937 vfs_mount_error(mp, "illegal acdirmin: %s", 938 opt); 939 error = EINVAL; 940 goto out; 941 } 942 args.flags |= NFSMNT_ACDIRMIN; 943 } 944 if (vfs_getopt(mp->mnt_optnew, "acdirmax", (void **)&opt, NULL) == 0) { 945 ret = sscanf(opt, "%d", &args.acdirmax); 946 if (ret != 1 || args.acdirmax < 0) { 947 vfs_mount_error(mp, "illegal acdirmax: %s", 948 opt); 949 error = EINVAL; 950 goto out; 951 } 952 args.flags |= NFSMNT_ACDIRMAX; 953 } 954 if (vfs_getopt(mp->mnt_optnew, "wcommitsize", (void **)&opt, NULL) == 0) { 955 ret = sscanf(opt, "%d", &args.wcommitsize); 956 if (ret != 1 || args.wcommitsize < 0) { 957 vfs_mount_error(mp, "illegal wcommitsize: %s", opt); 958 error = EINVAL; 959 goto out; 960 } 961 args.flags |= NFSMNT_WCOMMITSIZE; 962 } 963 if (vfs_getopt(mp->mnt_optnew, "timeout", (void **)&opt, NULL) == 0) { 964 ret = sscanf(opt, "%d", &args.timeo); 965 if (ret != 1 || args.timeo <= 0) { 966 vfs_mount_error(mp, "illegal timeout: %s", 967 opt); 968 error = EINVAL; 969 goto out; 970 } 971 args.flags |= NFSMNT_TIMEO; 972 } 973 if (vfs_getopt(mp->mnt_optnew, "nametimeo", (void **)&opt, NULL) == 0) { 974 ret = sscanf(opt, "%d", &nametimeo); 975 if (ret != 1 || nametimeo < 0) { 976 vfs_mount_error(mp, "illegal nametimeo: %s", opt); 977 error = EINVAL; 978 goto out; 979 } 980 } 981 if (vfs_getopt(mp->mnt_optnew, "negnametimeo", (void **)&opt, NULL) 982 == 0) { 983 ret = sscanf(opt, "%d", &negnametimeo); 984 if (ret != 1 || negnametimeo < 0) { 985 vfs_mount_error(mp, "illegal negnametimeo: %s", 986 opt); 987 error = EINVAL; 988 goto out; 989 } 990 } 991 if (vfs_getopt(mp->mnt_optnew, "sec", 992 (void **) &secname, NULL) == 0) 993 nfs_sec_name(secname, &args.flags); 994 995 if (mp->mnt_flag & MNT_UPDATE) { 996 struct nfsmount *nmp = VFSTONFS(mp); 997 998 if (nmp == NULL) { 999 error = EIO; 1000 goto out; 1001 } 1002 1003 /* 1004 * If a change from TCP->UDP is done and there are thread(s) 1005 * that have I/O RPC(s) in progress with a tranfer size 1006 * greater than NFS_MAXDGRAMDATA, those thread(s) will be 1007 * hung, retrying the RPC(s) forever. Usually these threads 1008 * will be seen doing an uninterruptible sleep on wait channel 1009 * "newnfsreq" (truncated to "newnfsre" by procstat). 1010 */ 1011 if (args.sotype == SOCK_DGRAM && nmp->nm_sotype == SOCK_STREAM) 1012 tprintf(td->td_proc, LOG_WARNING, 1013 "Warning: mount -u that changes TCP->UDP can result in hung threads\n"); 1014 1015 /* 1016 * When doing an update, we can't change version, 1017 * security, switch lockd strategies or change cookie 1018 * translation 1019 */ 1020 args.flags = (args.flags & 1021 ~(NFSMNT_NFSV3 | 1022 NFSMNT_NFSV4 | 1023 NFSMNT_KERB | 1024 NFSMNT_INTEGRITY | 1025 NFSMNT_PRIVACY | 1026 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) | 1027 (nmp->nm_flag & 1028 (NFSMNT_NFSV3 | 1029 NFSMNT_NFSV4 | 1030 NFSMNT_KERB | 1031 NFSMNT_INTEGRITY | 1032 NFSMNT_PRIVACY | 1033 NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)); 1034 nfs_decode_args(mp, nmp, &args, NULL, td->td_ucred, td); 1035 goto out; 1036 } 1037 1038 /* 1039 * Make the nfs_ip_paranoia sysctl serve as the default connection 1040 * or no-connection mode for those protocols that support 1041 * no-connection mode (the flag will be cleared later for protocols 1042 * that do not support no-connection mode). This will allow a client 1043 * to receive replies from a different IP then the request was 1044 * sent to. Note: default value for nfs_ip_paranoia is 1 (paranoid), 1045 * not 0. 1046 */ 1047 if (nfs_ip_paranoia == 0) 1048 args.flags |= NFSMNT_NOCONN; 1049 1050 if (has_nfs_args_opt != 0) { 1051 /* 1052 * In the 'nfs_args' case, the pointers in the args 1053 * structure are in userland - we copy them in here. 1054 */ 1055 if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX) { 1056 vfs_mount_error(mp, "Bad file handle"); 1057 error = EINVAL; 1058 goto out; 1059 } 1060 error = copyin((caddr_t)args.fh, (caddr_t)nfh, 1061 args.fhsize); 1062 if (error != 0) 1063 goto out; 1064 error = copyinstr(args.hostname, hst, MNAMELEN - 1, &hstlen); 1065 if (error != 0) 1066 goto out; 1067 bzero(&hst[hstlen], MNAMELEN - hstlen); 1068 args.hostname = hst; 1069 /* sockargs() call must be after above copyin() calls */ 1070 error = getsockaddr(&nam, (caddr_t)args.addr, 1071 args.addrlen); 1072 if (error != 0) 1073 goto out; 1074 } else { 1075 if (vfs_getopt(mp->mnt_optnew, "fh", (void **)&args.fh, 1076 &args.fhsize) == 0) { 1077 if (args.fhsize < 0 || args.fhsize > NFSX_FHMAX) { 1078 vfs_mount_error(mp, "Bad file handle"); 1079 error = EINVAL; 1080 goto out; 1081 } 1082 bcopy(args.fh, nfh, args.fhsize); 1083 } else { 1084 args.fhsize = 0; 1085 } 1086 (void) vfs_getopt(mp->mnt_optnew, "hostname", 1087 (void **)&args.hostname, &len); 1088 if (args.hostname == NULL) { 1089 vfs_mount_error(mp, "Invalid hostname"); 1090 error = EINVAL; 1091 goto out; 1092 } 1093 bcopy(args.hostname, hst, MNAMELEN); 1094 hst[MNAMELEN - 1] = '\0'; 1095 } 1096 1097 if (vfs_getopt(mp->mnt_optnew, "principal", (void **)&name, NULL) == 0) 1098 strlcpy(srvkrbname, name, sizeof (srvkrbname)); 1099 else 1100 snprintf(srvkrbname, sizeof (srvkrbname), "nfs@%s", hst); 1101 srvkrbnamelen = strlen(srvkrbname); 1102 1103 if (vfs_getopt(mp->mnt_optnew, "gssname", (void **)&name, NULL) == 0) 1104 strlcpy(krbname, name, sizeof (krbname)); 1105 else 1106 krbname[0] = '\0'; 1107 krbnamelen = strlen(krbname); 1108 1109 if (vfs_getopt(mp->mnt_optnew, "dirpath", (void **)&name, NULL) == 0) 1110 strlcpy(dirpath, name, sizeof (dirpath)); 1111 else 1112 dirpath[0] = '\0'; 1113 dirlen = strlen(dirpath); 1114 1115 if (has_nfs_args_opt == 0) { 1116 if (vfs_getopt(mp->mnt_optnew, "addr", 1117 (void **)&args.addr, &args.addrlen) == 0) { 1118 if (args.addrlen > SOCK_MAXADDRLEN) { 1119 error = ENAMETOOLONG; 1120 goto out; 1121 } 1122 nam = malloc(args.addrlen, M_SONAME, M_WAITOK); 1123 bcopy(args.addr, nam, args.addrlen); 1124 nam->sa_len = args.addrlen; 1125 } else { 1126 vfs_mount_error(mp, "No server address"); 1127 error = EINVAL; 1128 goto out; 1129 } 1130 } 1131 1132 args.fh = nfh; 1133 error = mountnfs(&args, mp, nam, hst, krbname, krbnamelen, dirpath, 1134 dirlen, srvkrbname, srvkrbnamelen, &vp, td->td_ucred, td, 1135 nametimeo, negnametimeo); 1136out: 1137 if (!error) { 1138 MNT_ILOCK(mp); 1139 mp->mnt_kern_flag |= MNTK_MPSAFE | MNTK_LOOKUP_SHARED | 1140 MNTK_NO_IOPF; 1141 MNT_IUNLOCK(mp); 1142 } 1143 return (error); 1144} 1145 1146 1147/* 1148 * VFS Operations. 1149 * 1150 * mount system call 1151 * It seems a bit dumb to copyinstr() the host and path here and then 1152 * bcopy() them in mountnfs(), but I wanted to detect errors before 1153 * doing the sockargs() call because sockargs() allocates an mbuf and 1154 * an error after that means that I have to release the mbuf. 1155 */ 1156/* ARGSUSED */ 1157static int 1158nfs_cmount(struct mntarg *ma, void *data, uint64_t flags) 1159{ 1160 int error; 1161 struct nfs_args args; 1162 1163 error = copyin(data, &args, sizeof (struct nfs_args)); 1164 if (error) 1165 return error; 1166 1167 ma = mount_arg(ma, "nfs_args", &args, sizeof args); 1168 1169 error = kernel_mount(ma, flags); 1170 return (error); 1171} 1172 1173/* 1174 * Common code for mount and mountroot 1175 */ 1176static int 1177mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, 1178 char *hst, u_char *krbname, int krbnamelen, u_char *dirpath, int dirlen, 1179 u_char *srvkrbname, int srvkrbnamelen, struct vnode **vpp, 1180 struct ucred *cred, struct thread *td, int nametimeo, int negnametimeo) 1181{ 1182 struct nfsmount *nmp; 1183 struct nfsnode *np; 1184 int error, trycnt, ret; 1185 struct nfsvattr nfsva; 1186 static u_int64_t clval = 0; 1187 1188 if (mp->mnt_flag & MNT_UPDATE) { 1189 nmp = VFSTONFS(mp); 1190 printf("%s: MNT_UPDATE is no longer handled here\n", __func__); 1191 FREE(nam, M_SONAME); 1192 return (0); 1193 } else { 1194 MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount) + 1195 krbnamelen + dirlen + srvkrbnamelen + 2, 1196 M_NEWNFSMNT, M_WAITOK | M_ZERO); 1197 TAILQ_INIT(&nmp->nm_bufq); 1198 if (clval == 0) 1199 clval = (u_int64_t)nfsboottime.tv_sec; 1200 nmp->nm_clval = clval++; 1201 nmp->nm_krbnamelen = krbnamelen; 1202 nmp->nm_dirpathlen = dirlen; 1203 nmp->nm_srvkrbnamelen = srvkrbnamelen; 1204 if (td->td_ucred->cr_uid != (uid_t)0) { 1205 /* 1206 * nm_uid is used to get KerberosV credentials for 1207 * the nfsv4 state handling operations if there is 1208 * no host based principal set. Use the uid of 1209 * this user if not root, since they are doing the 1210 * mount. I don't think setting this for root will 1211 * work, since root normally does not have user 1212 * credentials in a credentials cache. 1213 */ 1214 nmp->nm_uid = td->td_ucred->cr_uid; 1215 } else { 1216 /* 1217 * Just set to -1, so it won't be used. 1218 */ 1219 nmp->nm_uid = (uid_t)-1; 1220 } 1221 1222 /* Copy and null terminate all the names */ 1223 if (nmp->nm_krbnamelen > 0) { 1224 bcopy(krbname, nmp->nm_krbname, nmp->nm_krbnamelen); 1225 nmp->nm_name[nmp->nm_krbnamelen] = '\0'; 1226 } 1227 if (nmp->nm_dirpathlen > 0) { 1228 bcopy(dirpath, NFSMNT_DIRPATH(nmp), 1229 nmp->nm_dirpathlen); 1230 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen 1231 + 1] = '\0'; 1232 } 1233 if (nmp->nm_srvkrbnamelen > 0) { 1234 bcopy(srvkrbname, NFSMNT_SRVKRBNAME(nmp), 1235 nmp->nm_srvkrbnamelen); 1236 nmp->nm_name[nmp->nm_krbnamelen + nmp->nm_dirpathlen 1237 + nmp->nm_srvkrbnamelen + 2] = '\0'; 1238 } 1239 nmp->nm_sockreq.nr_cred = crhold(cred); 1240 mtx_init(&nmp->nm_sockreq.nr_mtx, "nfssock", NULL, MTX_DEF); 1241 mp->mnt_data = nmp; 1242 nmp->nm_getinfo = nfs_getnlminfo; 1243 nmp->nm_vinvalbuf = ncl_vinvalbuf; 1244 } 1245 vfs_getnewfsid(mp); 1246 nmp->nm_mountp = mp; 1247 mtx_init(&nmp->nm_mtx, "NFSmount lock", NULL, MTX_DEF | MTX_DUPOK); 1248 1249 /* 1250 * Since nfs_decode_args() might optionally set them, these 1251 * need to be set to defaults before the call, so that the 1252 * optional settings aren't overwritten. 1253 */ 1254 nmp->nm_nametimeo = nametimeo; 1255 nmp->nm_negnametimeo = negnametimeo; 1256 nmp->nm_timeo = NFS_TIMEO; 1257 nmp->nm_retry = NFS_RETRANS; 1258 nmp->nm_readahead = NFS_DEFRAHEAD; 1259 if (desiredvnodes >= 11000) 1260 nmp->nm_wcommitsize = hibufspace / (desiredvnodes / 1000); 1261 else 1262 nmp->nm_wcommitsize = hibufspace / 10; 1263 1264 nfs_decode_args(mp, nmp, argp, hst, cred, td); 1265 1266 /* 1267 * V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too 1268 * high, depending on whether we end up with negative offsets in 1269 * the client or server somewhere. 2GB-1 may be safer. 1270 * 1271 * For V3, ncl_fsinfo will adjust this as necessary. Assume maximum 1272 * that we can handle until we find out otherwise. 1273 * XXX Our "safe" limit on the client is what we can store in our 1274 * buffer cache using signed(!) block numbers. 1275 */ 1276 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) 1277 nmp->nm_maxfilesize = 0xffffffffLL; 1278 else 1279 nmp->nm_maxfilesize = OFF_MAX; 1280 1281 if ((argp->flags & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0) { 1282 nmp->nm_wsize = NFS_WSIZE; 1283 nmp->nm_rsize = NFS_RSIZE; 1284 nmp->nm_readdirsize = NFS_READDIRSIZE; 1285 } 1286 nmp->nm_numgrps = NFS_MAXGRPS; 1287 nmp->nm_tprintf_delay = nfs_tprintf_delay; 1288 if (nmp->nm_tprintf_delay < 0) 1289 nmp->nm_tprintf_delay = 0; 1290 nmp->nm_tprintf_initial_delay = nfs_tprintf_initial_delay; 1291 if (nmp->nm_tprintf_initial_delay < 0) 1292 nmp->nm_tprintf_initial_delay = 0; 1293 nmp->nm_fhsize = argp->fhsize; 1294 if (nmp->nm_fhsize > 0) 1295 bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); 1296 bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); 1297 nmp->nm_nam = nam; 1298 /* Set up the sockets and per-host congestion */ 1299 nmp->nm_sotype = argp->sotype; 1300 nmp->nm_soproto = argp->proto; 1301 nmp->nm_sockreq.nr_prog = NFS_PROG; 1302 if ((argp->flags & NFSMNT_NFSV4)) 1303 nmp->nm_sockreq.nr_vers = NFS_VER4; 1304 else if ((argp->flags & NFSMNT_NFSV3)) 1305 nmp->nm_sockreq.nr_vers = NFS_VER3; 1306 else 1307 nmp->nm_sockreq.nr_vers = NFS_VER2; 1308 1309 1310 if ((error = newnfs_connect(nmp, &nmp->nm_sockreq, cred, td, 0))) 1311 goto bad; 1312 1313 /* 1314 * A reference count is needed on the nfsnode representing the 1315 * remote root. If this object is not persistent, then backward 1316 * traversals of the mount point (i.e. "..") will not work if 1317 * the nfsnode gets flushed out of the cache. Ufs does not have 1318 * this problem, because one can identify root inodes by their 1319 * number == ROOTINO (2). 1320 */ 1321 if (nmp->nm_fhsize == 0 && (nmp->nm_flag & NFSMNT_NFSV4) && 1322 nmp->nm_dirpathlen > 0) { 1323 /* 1324 * If the fhsize on the mount point == 0 for V4, the mount 1325 * path needs to be looked up. 1326 */ 1327 trycnt = 3; 1328 do { 1329 error = nfsrpc_getdirpath(nmp, NFSMNT_DIRPATH(nmp), 1330 cred, td); 1331 if (error) 1332 (void) nfs_catnap(PZERO, error, "nfsgetdirp"); 1333 } while (error && --trycnt > 0); 1334 if (error) { 1335 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 1336 goto bad; 1337 } 1338 } 1339 if (nmp->nm_fhsize > 0) { 1340 /* 1341 * Set f_iosize to NFS_DIRBLKSIZ so that bo_bsize gets set 1342 * non-zero for the root vnode. f_iosize will be set correctly 1343 * by nfs_statfs() before any I/O occurs. 1344 */ 1345 mp->mnt_stat.f_iosize = NFS_DIRBLKSIZ; 1346 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, 1347 LK_EXCLUSIVE); 1348 if (error) 1349 goto bad; 1350 *vpp = NFSTOV(np); 1351 1352 /* 1353 * Get file attributes and transfer parameters for the 1354 * mountpoint. This has the side effect of filling in 1355 * (*vpp)->v_type with the correct value. 1356 */ 1357 ret = nfsrpc_getattrnovp(nmp, nmp->nm_fh, nmp->nm_fhsize, 1, 1358 cred, td, &nfsva, NULL); 1359 if (ret) { 1360 /* 1361 * Just set default values to get things going. 1362 */ 1363 NFSBZERO((caddr_t)&nfsva, sizeof (struct nfsvattr)); 1364 nfsva.na_vattr.va_type = VDIR; 1365 nfsva.na_vattr.va_mode = 0777; 1366 nfsva.na_vattr.va_nlink = 100; 1367 nfsva.na_vattr.va_uid = (uid_t)0; 1368 nfsva.na_vattr.va_gid = (gid_t)0; 1369 nfsva.na_vattr.va_fileid = 2; 1370 nfsva.na_vattr.va_gen = 1; 1371 nfsva.na_vattr.va_blocksize = NFS_FABLKSIZE; 1372 nfsva.na_vattr.va_size = 512 * 1024; 1373 } 1374 (void) nfscl_loadattrcache(vpp, &nfsva, NULL, NULL, 0, 1); 1375 if (argp->flags & NFSMNT_NFSV3) 1376 ncl_fsinfo(nmp, *vpp, cred, td); 1377 1378 /* Mark if the mount point supports NFSv4 ACLs. */ 1379 if ((argp->flags & NFSMNT_NFSV4) != 0 && nfsrv_useacl != 0 && 1380 ret == 0 && 1381 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) { 1382 MNT_ILOCK(mp); 1383 mp->mnt_flag |= MNT_NFS4ACLS; 1384 MNT_IUNLOCK(mp); 1385 } 1386 1387 /* 1388 * Lose the lock but keep the ref. 1389 */ 1390 NFSVOPUNLOCK(*vpp, 0); 1391 return (0); 1392 } 1393 error = EIO; 1394 1395bad: 1396 newnfs_disconnect(&nmp->nm_sockreq); 1397 crfree(nmp->nm_sockreq.nr_cred); 1398 mtx_destroy(&nmp->nm_sockreq.nr_mtx); 1399 mtx_destroy(&nmp->nm_mtx); 1400 FREE(nmp, M_NEWNFSMNT); 1401 FREE(nam, M_SONAME); 1402 return (error); 1403} 1404 1405/* 1406 * unmount system call 1407 */ 1408static int 1409nfs_unmount(struct mount *mp, int mntflags) 1410{ 1411 struct thread *td; 1412 struct nfsmount *nmp; 1413 int error, flags = 0, trycnt = 0; 1414 1415 td = curthread; 1416 1417 if (mntflags & MNT_FORCE) 1418 flags |= FORCECLOSE; 1419 nmp = VFSTONFS(mp); 1420 /* 1421 * Goes something like this.. 1422 * - Call vflush() to clear out vnodes for this filesystem 1423 * - Close the socket 1424 * - Free up the data structures 1425 */ 1426 /* In the forced case, cancel any outstanding requests. */ 1427 if (mntflags & MNT_FORCE) { 1428 error = newnfs_nmcancelreqs(nmp); 1429 if (error) 1430 goto out; 1431 /* For a forced close, get rid of the renew thread now */ 1432 nfscl_umount(nmp, td); 1433 } 1434 /* We hold 1 extra ref on the root vnode; see comment in mountnfs(). */ 1435 do { 1436 error = vflush(mp, 1, flags, td); 1437 if ((mntflags & MNT_FORCE) && error != 0 && ++trycnt < 30) 1438 (void) nfs_catnap(PSOCK, error, "newndm"); 1439 } while ((mntflags & MNT_FORCE) && error != 0 && trycnt < 30); 1440 if (error) 1441 goto out; 1442 1443 /* 1444 * We are now committed to the unmount. 1445 */ 1446 if ((mntflags & MNT_FORCE) == 0) 1447 nfscl_umount(nmp, td); 1448 newnfs_disconnect(&nmp->nm_sockreq); 1449 crfree(nmp->nm_sockreq.nr_cred); 1450 FREE(nmp->nm_nam, M_SONAME); 1451 1452 mtx_destroy(&nmp->nm_sockreq.nr_mtx); 1453 mtx_destroy(&nmp->nm_mtx); 1454 FREE(nmp, M_NEWNFSMNT); 1455out: 1456 return (error); 1457} 1458 1459/* 1460 * Return root of a filesystem 1461 */ 1462static int 1463nfs_root(struct mount *mp, int flags, struct vnode **vpp) 1464{ 1465 struct vnode *vp; 1466 struct nfsmount *nmp; 1467 struct nfsnode *np; 1468 int error; 1469 1470 nmp = VFSTONFS(mp); 1471 error = ncl_nget(mp, nmp->nm_fh, nmp->nm_fhsize, &np, flags); 1472 if (error) 1473 return error; 1474 vp = NFSTOV(np); 1475 /* 1476 * Get transfer parameters and attributes for root vnode once. 1477 */ 1478 mtx_lock(&nmp->nm_mtx); 1479 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) { 1480 mtx_unlock(&nmp->nm_mtx); 1481 ncl_fsinfo(nmp, vp, curthread->td_ucred, curthread); 1482 } else 1483 mtx_unlock(&nmp->nm_mtx); 1484 if (vp->v_type == VNON) 1485 vp->v_type = VDIR; 1486 vp->v_vflag |= VV_ROOT; 1487 *vpp = vp; 1488 return (0); 1489} 1490 1491/* 1492 * Flush out the buffer cache 1493 */ 1494/* ARGSUSED */ 1495static int 1496nfs_sync(struct mount *mp, int waitfor) 1497{ 1498 struct vnode *vp, *mvp; 1499 struct thread *td; 1500 int error, allerror = 0; 1501 1502 td = curthread; 1503 1504 MNT_ILOCK(mp); 1505 /* 1506 * If a forced dismount is in progress, return from here so that 1507 * the umount(2) syscall doesn't get stuck in VFS_SYNC() before 1508 * calling VFS_UNMOUNT(). 1509 */ 1510 if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) { 1511 MNT_IUNLOCK(mp); 1512 return (EBADF); 1513 } 1514 MNT_IUNLOCK(mp); 1515 1516 /* 1517 * Force stale buffer cache information to be flushed. 1518 */ 1519loop: 1520 MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { 1521 /* XXX Racy bv_cnt check. */ 1522 if (NFSVOPISLOCKED(vp) || vp->v_bufobj.bo_dirty.bv_cnt == 0 || 1523 waitfor == MNT_LAZY) { 1524 VI_UNLOCK(vp); 1525 continue; 1526 } 1527 if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { 1528 MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 1529 goto loop; 1530 } 1531 error = VOP_FSYNC(vp, waitfor, td); 1532 if (error) 1533 allerror = error; 1534 NFSVOPUNLOCK(vp, 0); 1535 vrele(vp); 1536 } 1537 return (allerror); 1538} 1539 1540static int 1541nfs_sysctl(struct mount *mp, fsctlop_t op, struct sysctl_req *req) 1542{ 1543 struct nfsmount *nmp = VFSTONFS(mp); 1544 struct vfsquery vq; 1545 int error; 1546 1547 bzero(&vq, sizeof(vq)); 1548 switch (op) { 1549#if 0 1550 case VFS_CTL_NOLOCKS: 1551 val = (nmp->nm_flag & NFSMNT_NOLOCKS) ? 1 : 0; 1552 if (req->oldptr != NULL) { 1553 error = SYSCTL_OUT(req, &val, sizeof(val)); 1554 if (error) 1555 return (error); 1556 } 1557 if (req->newptr != NULL) { 1558 error = SYSCTL_IN(req, &val, sizeof(val)); 1559 if (error) 1560 return (error); 1561 if (val) 1562 nmp->nm_flag |= NFSMNT_NOLOCKS; 1563 else 1564 nmp->nm_flag &= ~NFSMNT_NOLOCKS; 1565 } 1566 break; 1567#endif 1568 case VFS_CTL_QUERY: 1569 mtx_lock(&nmp->nm_mtx); 1570 if (nmp->nm_state & NFSSTA_TIMEO) 1571 vq.vq_flags |= VQ_NOTRESP; 1572 mtx_unlock(&nmp->nm_mtx); 1573#if 0 1574 if (!(nmp->nm_flag & NFSMNT_NOLOCKS) && 1575 (nmp->nm_state & NFSSTA_LOCKTIMEO)) 1576 vq.vq_flags |= VQ_NOTRESPLOCK; 1577#endif 1578 error = SYSCTL_OUT(req, &vq, sizeof(vq)); 1579 break; 1580 case VFS_CTL_TIMEO: 1581 if (req->oldptr != NULL) { 1582 error = SYSCTL_OUT(req, &nmp->nm_tprintf_initial_delay, 1583 sizeof(nmp->nm_tprintf_initial_delay)); 1584 if (error) 1585 return (error); 1586 } 1587 if (req->newptr != NULL) { 1588 error = vfs_suser(mp, req->td); 1589 if (error) 1590 return (error); 1591 error = SYSCTL_IN(req, &nmp->nm_tprintf_initial_delay, 1592 sizeof(nmp->nm_tprintf_initial_delay)); 1593 if (error) 1594 return (error); 1595 if (nmp->nm_tprintf_initial_delay < 0) 1596 nmp->nm_tprintf_initial_delay = 0; 1597 } 1598 break; 1599 default: 1600 return (ENOTSUP); 1601 } 1602 return (0); 1603} 1604 1605/* 1606 * Extract the information needed by the nlm from the nfs vnode. 1607 */ 1608static void 1609nfs_getnlminfo(struct vnode *vp, uint8_t *fhp, size_t *fhlenp, 1610 struct sockaddr_storage *sp, int *is_v3p, off_t *sizep, 1611 struct timeval *timeop) 1612{ 1613 struct nfsmount *nmp; 1614 struct nfsnode *np = VTONFS(vp); 1615 1616 nmp = VFSTONFS(vp->v_mount); 1617 if (fhlenp != NULL) 1618 *fhlenp = (size_t)np->n_fhp->nfh_len; 1619 if (fhp != NULL) 1620 bcopy(np->n_fhp->nfh_fh, fhp, np->n_fhp->nfh_len); 1621 if (sp != NULL) 1622 bcopy(nmp->nm_nam, sp, min(nmp->nm_nam->sa_len, sizeof(*sp))); 1623 if (is_v3p != NULL) 1624 *is_v3p = NFS_ISV3(vp); 1625 if (sizep != NULL) 1626 *sizep = np->n_size; 1627 if (timeop != NULL) { 1628 timeop->tv_sec = nmp->nm_timeo / NFS_HZ; 1629 timeop->tv_usec = (nmp->nm_timeo % NFS_HZ) * (1000000 / NFS_HZ); 1630 } 1631} 1632 1633/* 1634 * This function prints out an option name, based on the conditional 1635 * argument. 1636 */ 1637static __inline void nfscl_printopt(struct nfsmount *nmp, int testval, 1638 char *opt, char **buf, size_t *blen) 1639{ 1640 int len; 1641 1642 if (testval != 0 && *blen > strlen(opt)) { 1643 len = snprintf(*buf, *blen, "%s", opt); 1644 if (len != strlen(opt)) 1645 printf("EEK!!\n"); 1646 *buf += len; 1647 *blen -= len; 1648 } 1649} 1650 1651/* 1652 * This function printf out an options integer value. 1653 */ 1654static __inline void nfscl_printoptval(struct nfsmount *nmp, int optval, 1655 char *opt, char **buf, size_t *blen) 1656{ 1657 int len; 1658 1659 if (*blen > strlen(opt) + 1) { 1660 /* Could result in truncated output string. */ 1661 len = snprintf(*buf, *blen, "%s=%d", opt, optval); 1662 if (len < *blen) { 1663 *buf += len; 1664 *blen -= len; 1665 } 1666 } 1667} 1668 1669/* 1670 * Load the option flags and values into the buffer. 1671 */ 1672void nfscl_retopts(struct nfsmount *nmp, char *buffer, size_t buflen) 1673{ 1674 char *buf; 1675 size_t blen; 1676 1677 buf = buffer; 1678 blen = buflen; 1679 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV4) != 0, "nfsv4", &buf, 1680 &blen); 1681 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NFSV3) != 0, "nfsv3", &buf, 1682 &blen); 1683 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NFSV4)) == 0, 1684 "nfsv2", &buf, &blen); 1685 nfscl_printopt(nmp, nmp->nm_sotype == SOCK_STREAM, ",tcp", &buf, &blen); 1686 nfscl_printopt(nmp, nmp->nm_sotype != SOCK_STREAM, ",udp", &buf, &blen); 1687 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RESVPORT) != 0, ",resvport", 1688 &buf, &blen); 1689 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCONN) != 0, ",noconn", 1690 &buf, &blen); 1691 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) == 0, ",hard", &buf, 1692 &blen); 1693 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_SOFT) != 0, ",soft", &buf, 1694 &blen); 1695 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_INT) != 0, ",intr", &buf, 1696 &blen); 1697 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) == 0, ",cto", &buf, 1698 &blen); 1699 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_NOCTO) != 0, ",nocto", &buf, 1700 &blen); 1701 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) == 1702 0, ",lockd", &buf, &blen); 1703 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_NOLOCKD | NFSMNT_NFSV4)) == 1704 NFSMNT_NOLOCKD, ",nolockd", &buf, &blen); 1705 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_RDIRPLUS) != 0, ",rdirplus", 1706 &buf, &blen); 1707 nfscl_printopt(nmp, (nmp->nm_flag & NFSMNT_KERB) == 0, ",sec=sys", 1708 &buf, &blen); 1709 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 1710 NFSMNT_PRIVACY)) == NFSMNT_KERB, ",sec=krb5", &buf, &blen); 1711 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 1712 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_INTEGRITY), ",sec=krb5i", 1713 &buf, &blen); 1714 nfscl_printopt(nmp, (nmp->nm_flag & (NFSMNT_KERB | NFSMNT_INTEGRITY | 1715 NFSMNT_PRIVACY)) == (NFSMNT_KERB | NFSMNT_PRIVACY), ",sec=krb5p", 1716 &buf, &blen); 1717 nfscl_printoptval(nmp, nmp->nm_acdirmin, ",acdirmin", &buf, &blen); 1718 nfscl_printoptval(nmp, nmp->nm_acdirmax, ",acdirmax", &buf, &blen); 1719 nfscl_printoptval(nmp, nmp->nm_acregmin, ",acregmin", &buf, &blen); 1720 nfscl_printoptval(nmp, nmp->nm_acregmax, ",acregmax", &buf, &blen); 1721 nfscl_printoptval(nmp, nmp->nm_nametimeo, ",nametimeo", &buf, &blen); 1722 nfscl_printoptval(nmp, nmp->nm_negnametimeo, ",negnametimeo", &buf, 1723 &blen); 1724 nfscl_printoptval(nmp, nmp->nm_rsize, ",rsize", &buf, &blen); 1725 nfscl_printoptval(nmp, nmp->nm_wsize, ",wsize", &buf, &blen); 1726 nfscl_printoptval(nmp, nmp->nm_readdirsize, ",readdirsize", &buf, 1727 &blen); 1728 nfscl_printoptval(nmp, nmp->nm_readahead, ",readahead", &buf, &blen); 1729 nfscl_printoptval(nmp, nmp->nm_wcommitsize, ",wcommitsize", &buf, 1730 &blen); 1731 nfscl_printoptval(nmp, nmp->nm_timeo, ",timeout", &buf, &blen); 1732 nfscl_printoptval(nmp, nmp->nm_retry, ",retrans", &buf, &blen); 1733} 1734 1735