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