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