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