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