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