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