1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Copyright (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. 26 * All rights reserved. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/param.h> 32 #include <sys/types.h> 33 #include <sys/systm.h> 34 #include <sys/cred.h> 35 #include <sys/vfs.h> 36 #include <sys/vnode.h> 37 #include <sys/pathname.h> 38 #include <sys/sysmacros.h> 39 #include <sys/kmem.h> 40 #include <sys/mkdev.h> 41 #include <sys/mount.h> 42 #include <sys/mntent.h> 43 #include <sys/statvfs.h> 44 #include <sys/errno.h> 45 #include <sys/debug.h> 46 #include <sys/cmn_err.h> 47 #include <sys/utsname.h> 48 #include <sys/bootconf.h> 49 #include <sys/modctl.h> 50 #include <sys/acl.h> 51 #include <sys/flock.h> 52 #include <sys/policy.h> 53 #include <sys/zone.h> 54 #include <sys/class.h> 55 #include <sys/socket.h> 56 #include <sys/netconfig.h> 57 #include <sys/mntent.h> 58 #include <sys/tsol/label.h> 59 60 #include <rpc/types.h> 61 #include <rpc/auth.h> 62 #include <rpc/clnt.h> 63 64 #include <nfs/nfs.h> 65 #include <nfs/nfs_clnt.h> 66 #include <nfs/rnode.h> 67 #include <nfs/mount.h> 68 #include <nfs/nfs_acl.h> 69 70 #include <fs/fs_subr.h> 71 72 /* 73 * From rpcsec module (common/rpcsec). 74 */ 75 extern int sec_clnt_loadinfo(struct sec_data *, struct sec_data **, model_t); 76 extern void sec_clnt_freeinfo(struct sec_data *); 77 78 static int pathconf_get(struct mntinfo *, model_t, struct nfs_args *); 79 static void pathconf_rele(struct mntinfo *); 80 81 /* 82 * The order and contents of this structure must be kept in sync with that of 83 * rfsreqcnt_v2_tmpl in nfs_stats.c 84 */ 85 static char *rfsnames_v2[] = { 86 "null", "getattr", "setattr", "unused", "lookup", "readlink", "read", 87 "unused", "write", "create", "remove", "rename", "link", "symlink", 88 "mkdir", "rmdir", "readdir", "fsstat" 89 }; 90 91 /* 92 * This table maps from NFS protocol number into call type. 93 * Zero means a "Lookup" type call 94 * One means a "Read" type call 95 * Two means a "Write" type call 96 * This is used to select a default time-out. 97 */ 98 static uchar_t call_type_v2[] = { 99 0, 0, 1, 0, 0, 0, 1, 100 0, 2, 2, 2, 2, 2, 2, 101 2, 2, 1, 0 102 }; 103 104 /* 105 * Similar table, but to determine which timer to use 106 * (only real reads and writes!) 107 */ 108 static uchar_t timer_type_v2[] = { 109 0, 0, 0, 0, 0, 0, 1, 110 0, 2, 0, 0, 0, 0, 0, 111 0, 0, 1, 0 112 }; 113 114 /* 115 * This table maps from NFS protocol number into a call type 116 * for the semisoft mount option. 117 * Zero means do not repeat operation. 118 * One means repeat. 119 */ 120 static uchar_t ss_call_type_v2[] = { 121 0, 0, 1, 0, 0, 0, 0, 122 0, 1, 1, 1, 1, 1, 1, 123 1, 1, 0, 0 124 }; 125 126 /* 127 * nfs vfs operations. 128 */ 129 static int nfs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); 130 static int nfs_unmount(vfs_t *, int, cred_t *); 131 static int nfs_root(vfs_t *, vnode_t **); 132 static int nfs_statvfs(vfs_t *, struct statvfs64 *); 133 static int nfs_sync(vfs_t *, short, cred_t *); 134 static int nfs_vget(vfs_t *, vnode_t **, fid_t *); 135 static int nfs_mountroot(vfs_t *, whymountroot_t); 136 static void nfs_freevfs(vfs_t *); 137 138 static int nfsrootvp(vnode_t **, vfs_t *, struct servinfo *, 139 int, cred_t *, zone_t *); 140 141 /* 142 * Initialize the vfs structure 143 */ 144 145 int nfsfstyp; 146 vfsops_t *nfs_vfsops; 147 148 /* 149 * Debug variable to check for rdma based 150 * transport startup and cleanup. Controlled 151 * through /etc/system. Off by default. 152 */ 153 int rdma_debug = 0; 154 155 int 156 nfsinit(int fstyp, char *name) 157 { 158 static const fs_operation_def_t nfs_vfsops_template[] = { 159 VFSNAME_MOUNT, nfs_mount, 160 VFSNAME_UNMOUNT, nfs_unmount, 161 VFSNAME_ROOT, nfs_root, 162 VFSNAME_STATVFS, nfs_statvfs, 163 VFSNAME_SYNC, (fs_generic_func_p) nfs_sync, 164 VFSNAME_VGET, nfs_vget, 165 VFSNAME_MOUNTROOT, nfs_mountroot, 166 VFSNAME_FREEVFS, (fs_generic_func_p)nfs_freevfs, 167 NULL, NULL 168 }; 169 int error; 170 171 error = vfs_setfsops(fstyp, nfs_vfsops_template, &nfs_vfsops); 172 if (error != 0) { 173 zcmn_err(GLOBAL_ZONEID, CE_WARN, 174 "nfsinit: bad vfs ops template"); 175 return (error); 176 } 177 178 error = vn_make_ops(name, nfs_vnodeops_template, &nfs_vnodeops); 179 if (error != 0) { 180 (void) vfs_freevfsops_by_type(fstyp); 181 zcmn_err(GLOBAL_ZONEID, CE_WARN, 182 "nfsinit: bad vnode ops template"); 183 return (error); 184 } 185 186 187 nfsfstyp = fstyp; 188 189 return (0); 190 } 191 192 void 193 nfsfini(void) 194 { 195 } 196 197 /* 198 * nfs mount vfsop 199 * Set up mount info record and attach it to vfs struct. 200 */ 201 static int 202 nfs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 203 { 204 char *data = uap->dataptr; 205 int error; 206 vnode_t *rtvp; /* the server's root */ 207 mntinfo_t *mi; /* mount info, pointed at by vfs */ 208 size_t hlen; /* length of hostname */ 209 size_t nlen; /* length of netname */ 210 char netname[SYS_NMLN]; /* server's netname */ 211 struct netbuf addr; /* server's address */ 212 struct netbuf syncaddr; /* AUTH_DES time sync addr */ 213 struct knetconfig *knconf; /* transport knetconfig structure */ 214 struct knetconfig *rdma_knconf; /* rdma transport structure */ 215 rnode_t *rp; 216 struct servinfo *svp; /* nfs server info */ 217 struct servinfo *svp_tail = NULL; /* previous nfs server info */ 218 struct servinfo *svp_head; /* first nfs server info */ 219 struct servinfo *svp_2ndlast; /* 2nd last in the server info list */ 220 struct sec_data *secdata; /* security data */ 221 STRUCT_DECL(nfs_args, args); /* nfs mount arguments */ 222 STRUCT_DECL(knetconfig, knconf_tmp); 223 STRUCT_DECL(netbuf, addr_tmp); 224 int flags, addr_type; 225 char *p, *pf; 226 zone_t *zone = nfs_zone(); 227 zone_t *mntzone = NULL; 228 229 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 230 return (error); 231 232 if (mvp->v_type != VDIR) 233 return (ENOTDIR); 234 235 /* 236 * get arguments 237 * 238 * nfs_args is now versioned and is extensible, so 239 * uap->datalen might be different from sizeof (args) 240 * in a compatible situation. 241 */ 242 more: 243 STRUCT_INIT(args, get_udatamodel()); 244 bzero(STRUCT_BUF(args), SIZEOF_STRUCT(nfs_args, DATAMODEL_NATIVE)); 245 if (copyin(data, STRUCT_BUF(args), MIN(uap->datalen, 246 STRUCT_SIZE(args)))) 247 return (EFAULT); 248 249 flags = STRUCT_FGET(args, flags); 250 251 if (uap->flags & MS_REMOUNT) { 252 size_t n; 253 char name[FSTYPSZ]; 254 255 if (uap->flags & MS_SYSSPACE) 256 error = copystr(uap->fstype, name, FSTYPSZ, &n); 257 else 258 error = copyinstr(uap->fstype, name, FSTYPSZ, &n); 259 260 if (error) { 261 if (error == ENAMETOOLONG) 262 return (EINVAL); 263 return (error); 264 } 265 266 /* 267 * This check is to ensure that the request is a 268 * genuine nfs remount request. 269 */ 270 271 if (strncmp(name, "nfs", 3) != 0) 272 return (EINVAL); 273 274 /* 275 * If the request changes the locking type, disallow the 276 * remount, 277 * because it's questionable whether we can transfer the 278 * locking state correctly. 279 * 280 * Remounts need to save the pathconf information. 281 * Part of the infamous static kludge. 282 */ 283 284 if ((mi = VFTOMI(vfsp)) != NULL) { 285 uint_t new_mi_llock; 286 uint_t old_mi_llock; 287 288 new_mi_llock = (flags & NFSMNT_LLOCK) ? 1 : 0; 289 old_mi_llock = (mi->mi_flags & MI_LLOCK) ? 1 : 0; 290 if (old_mi_llock != new_mi_llock) 291 return (EBUSY); 292 } 293 return (pathconf_get((struct mntinfo *)vfsp->vfs_data, 294 get_udatamodel(), STRUCT_BUF(args))); 295 } 296 297 mutex_enter(&mvp->v_lock); 298 if (!(uap->flags & MS_OVERLAY) && 299 (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { 300 mutex_exit(&mvp->v_lock); 301 return (EBUSY); 302 } 303 mutex_exit(&mvp->v_lock); 304 305 /* make sure things are zeroed for errout: */ 306 rtvp = NULL; 307 mi = NULL; 308 addr.buf = NULL; 309 syncaddr.buf = NULL; 310 secdata = NULL; 311 312 /* 313 * A valid knetconfig structure is required. 314 */ 315 if (!(flags & NFSMNT_KNCONF)) 316 return (EINVAL); 317 318 /* 319 * Allocate a servinfo struct. 320 */ 321 svp = kmem_zalloc(sizeof (*svp), KM_SLEEP); 322 mutex_init(&svp->sv_lock, NULL, MUTEX_DEFAULT, NULL); 323 if (svp_tail) { 324 svp_2ndlast = svp_tail; 325 svp_tail->sv_next = svp; 326 } else { 327 svp_head = svp; 328 svp_2ndlast = svp; 329 } 330 331 svp_tail = svp; 332 333 /* 334 * Allocate space for a knetconfig structure and 335 * its strings and copy in from user-land. 336 */ 337 knconf = kmem_zalloc(sizeof (*knconf), KM_SLEEP); 338 svp->sv_knconf = knconf; 339 STRUCT_INIT(knconf_tmp, get_udatamodel()); 340 if (copyin(STRUCT_FGETP(args, knconf), STRUCT_BUF(knconf_tmp), 341 STRUCT_SIZE(knconf_tmp))) { 342 sv_free(svp_head); 343 return (EFAULT); 344 } 345 346 knconf->knc_semantics = STRUCT_FGET(knconf_tmp, knc_semantics); 347 knconf->knc_protofmly = STRUCT_FGETP(knconf_tmp, knc_protofmly); 348 knconf->knc_proto = STRUCT_FGETP(knconf_tmp, knc_proto); 349 if (get_udatamodel() != DATAMODEL_LP64) { 350 knconf->knc_rdev = expldev(STRUCT_FGET(knconf_tmp, knc_rdev)); 351 } else { 352 knconf->knc_rdev = STRUCT_FGET(knconf_tmp, knc_rdev); 353 } 354 355 pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 356 p = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 357 error = copyinstr(knconf->knc_protofmly, pf, KNC_STRSIZE, NULL); 358 if (error) { 359 kmem_free(pf, KNC_STRSIZE); 360 kmem_free(p, KNC_STRSIZE); 361 sv_free(svp_head); 362 return (error); 363 } 364 error = copyinstr(knconf->knc_proto, p, KNC_STRSIZE, NULL); 365 if (error) { 366 kmem_free(pf, KNC_STRSIZE); 367 kmem_free(p, KNC_STRSIZE); 368 sv_free(svp_head); 369 return (error); 370 } 371 knconf->knc_protofmly = pf; 372 knconf->knc_proto = p; 373 374 /* 375 * Get server address 376 */ 377 STRUCT_INIT(addr_tmp, get_udatamodel()); 378 if (copyin(STRUCT_FGETP(args, addr), STRUCT_BUF(addr_tmp), 379 STRUCT_SIZE(addr_tmp))) { 380 addr.buf = NULL; 381 error = EFAULT; 382 } else { 383 char *userbufptr; 384 385 userbufptr = addr.buf = STRUCT_FGETP(addr_tmp, buf); 386 addr.len = STRUCT_FGET(addr_tmp, len); 387 addr.buf = kmem_alloc(addr.len, KM_SLEEP); 388 addr.maxlen = addr.len; 389 if (copyin(userbufptr, addr.buf, addr.len)) 390 error = EFAULT; 391 } 392 svp->sv_addr = addr; 393 if (error) 394 goto errout; 395 396 /* 397 * Get the root fhandle 398 */ 399 if (copyin(STRUCT_FGETP(args, fh), &(svp->sv_fhandle.fh_buf), 400 NFS_FHSIZE)) { 401 error = EFAULT; 402 goto errout; 403 } 404 svp->sv_fhandle.fh_len = NFS_FHSIZE; 405 406 /* 407 * Get server's hostname 408 */ 409 if (flags & NFSMNT_HOSTNAME) { 410 error = copyinstr(STRUCT_FGETP(args, hostname), 411 netname, sizeof (netname), &hlen); 412 if (error) 413 goto errout; 414 } else { 415 char *p = "unknown-host"; 416 hlen = strlen(p) + 1; 417 (void) strcpy(netname, p); 418 } 419 svp->sv_hostnamelen = hlen; 420 svp->sv_hostname = kmem_alloc(svp->sv_hostnamelen, KM_SLEEP); 421 (void) strcpy(svp->sv_hostname, netname); 422 423 /* 424 * RDMA MOUNT SUPPORT FOR NFS v2: 425 * Establish, is it possible to use RDMA, if so overload the 426 * knconf with rdma specific knconf and free the orignal. 427 */ 428 if ((flags & NFSMNT_TRYRDMA) || (flags & NFSMNT_DORDMA)) { 429 /* 430 * Determine the addr type for RDMA, IPv4 or v6. 431 */ 432 if (strcmp(svp->sv_knconf->knc_protofmly, NC_INET) == 0) 433 addr_type = AF_INET; 434 else if (strcmp(svp->sv_knconf->knc_protofmly, NC_INET6) == 0) 435 addr_type = AF_INET6; 436 437 if (rdma_reachable(addr_type, &svp->sv_addr, 438 &rdma_knconf) == 0) { 439 /* 440 * If successful, hijack, the orignal knconf and 441 * replace with a new one, depending on the flags. 442 */ 443 svp->sv_origknconf = svp->sv_knconf; 444 svp->sv_knconf = rdma_knconf; 445 knconf = rdma_knconf; 446 } else { 447 if (flags & NFSMNT_TRYRDMA) { 448 #ifdef DEBUG 449 if (rdma_debug) 450 zcmn_err(getzoneid(), CE_WARN, 451 "no RDMA onboard, revert\n"); 452 #endif 453 } 454 455 if (flags & NFSMNT_DORDMA) { 456 /* 457 * If proto=rdma is specified and no RDMA 458 * path to this server is avialable then 459 * ditch this server. 460 * This is not included in the mountable 461 * server list or the replica list. 462 * Check if more servers are specified; 463 * Failover case, otherwise bail out of mount. 464 */ 465 if (STRUCT_FGET(args, nfs_args_ext) == 466 NFS_ARGS_EXTB && STRUCT_FGETP(args, 467 nfs_ext_u.nfs_extB.next) != NULL) { 468 if (uap->flags & MS_RDONLY && 469 !(flags & NFSMNT_SOFT)) { 470 data = (char *) 471 STRUCT_FGETP(args, 472 nfs_ext_u.nfs_extB.next); 473 if (svp_head->sv_next == NULL) { 474 svp_tail = NULL; 475 svp_2ndlast = NULL; 476 sv_free(svp_head); 477 goto more; 478 } else { 479 svp_tail = svp_2ndlast; 480 svp_2ndlast->sv_next = 481 NULL; 482 sv_free(svp); 483 goto more; 484 } 485 } 486 } else { 487 /* 488 * This is the last server specified 489 * in the nfs_args list passed down 490 * and its not rdma capable. 491 */ 492 if (svp_head->sv_next == NULL) { 493 /* 494 * Is this the only one 495 */ 496 error = EINVAL; 497 #ifdef DEBUG 498 if (rdma_debug) 499 zcmn_err(getzoneid(), 500 CE_WARN, 501 "No RDMA srv"); 502 #endif 503 goto errout; 504 } else { 505 /* 506 * There is list, since some 507 * servers specified before 508 * this passed all requirements 509 */ 510 svp_tail = svp_2ndlast; 511 svp_2ndlast->sv_next = NULL; 512 sv_free(svp); 513 goto proceed; 514 } 515 } 516 } 517 } 518 } 519 520 /* 521 * Get the extention data which has the new security data structure. 522 */ 523 if (flags & NFSMNT_NEWARGS) { 524 switch (STRUCT_FGET(args, nfs_args_ext)) { 525 case NFS_ARGS_EXTA: 526 case NFS_ARGS_EXTB: 527 /* 528 * Indicating the application is using the new 529 * sec_data structure to pass in the security 530 * data. 531 */ 532 if (STRUCT_FGETP(args, 533 nfs_ext_u.nfs_extA.secdata) == NULL) { 534 error = EINVAL; 535 } else { 536 error = sec_clnt_loadinfo( 537 (struct sec_data *)STRUCT_FGETP(args, 538 nfs_ext_u.nfs_extA.secdata), 539 &secdata, get_udatamodel()); 540 } 541 break; 542 543 default: 544 error = EINVAL; 545 break; 546 } 547 } else if (flags & NFSMNT_SECURE) { 548 /* 549 * Keep this for backward compatibility to support 550 * NFSMNT_SECURE/NFSMNT_RPCTIMESYNC flags. 551 */ 552 if (STRUCT_FGETP(args, syncaddr) == NULL) { 553 error = EINVAL; 554 } else { 555 /* 556 * get time sync address. 557 */ 558 if (copyin(STRUCT_FGETP(args, syncaddr), &addr_tmp, 559 STRUCT_SIZE(addr_tmp))) { 560 syncaddr.buf = NULL; 561 error = EFAULT; 562 } else { 563 char *userbufptr; 564 565 userbufptr = syncaddr.buf = 566 STRUCT_FGETP(addr_tmp, buf); 567 syncaddr.len = 568 STRUCT_FGET(addr_tmp, len); 569 syncaddr.buf = kmem_alloc(syncaddr.len, 570 KM_SLEEP); 571 syncaddr.maxlen = syncaddr.len; 572 573 if (copyin(userbufptr, syncaddr.buf, 574 syncaddr.len)) 575 error = EFAULT; 576 } 577 578 /* 579 * get server's netname 580 */ 581 if (!error) { 582 error = copyinstr(STRUCT_FGETP(args, netname), 583 netname, sizeof (netname), &nlen); 584 netname[nlen] = '\0'; 585 } 586 587 if (error && syncaddr.buf != NULL) { 588 kmem_free(syncaddr.buf, syncaddr.len); 589 syncaddr.buf = NULL; 590 } 591 } 592 593 /* 594 * Move security related data to the sec_data structure. 595 */ 596 if (!error) { 597 dh_k4_clntdata_t *data; 598 char *pf, *p; 599 600 secdata = kmem_alloc(sizeof (*secdata), KM_SLEEP); 601 if (flags & NFSMNT_RPCTIMESYNC) 602 secdata->flags |= AUTH_F_RPCTIMESYNC; 603 data = kmem_alloc(sizeof (*data), KM_SLEEP); 604 data->syncaddr = syncaddr; 605 606 /* 607 * duplicate the knconf information for the 608 * new opaque data. 609 */ 610 data->knconf = kmem_alloc(sizeof (*knconf), KM_SLEEP); 611 *data->knconf = *knconf; 612 pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 613 p = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 614 bcopy(knconf->knc_protofmly, pf, KNC_STRSIZE); 615 bcopy(knconf->knc_proto, pf, KNC_STRSIZE); 616 data->knconf->knc_protofmly = pf; 617 data->knconf->knc_proto = p; 618 619 /* move server netname to the sec_data structure */ 620 if (nlen != 0) { 621 data->netname = kmem_alloc(nlen, KM_SLEEP); 622 bcopy(netname, data->netname, nlen); 623 data->netnamelen = (int)nlen; 624 } 625 secdata->secmod = secdata->rpcflavor = AUTH_DES; 626 secdata->data = (caddr_t)data; 627 } 628 } else { 629 secdata = kmem_alloc(sizeof (*secdata), KM_SLEEP); 630 secdata->secmod = secdata->rpcflavor = AUTH_UNIX; 631 secdata->data = NULL; 632 } 633 svp->sv_secdata = secdata; 634 if (error) 635 goto errout; 636 637 /* 638 * See bug 1180236. 639 * If mount secure failed, we will fall back to AUTH_NONE 640 * and try again. nfs3rootvp() will turn this back off. 641 * 642 * The NFS Version 2 mount uses GETATTR and STATFS procedures. 643 * The server does not care if these procedures have the proper 644 * authentication flavor, so if mount retries using AUTH_NONE 645 * that does not require a credential setup for root then the 646 * automounter would work without requiring root to be 647 * keylogged into AUTH_DES. 648 */ 649 if (secdata->rpcflavor != AUTH_UNIX && 650 secdata->rpcflavor != AUTH_LOOPBACK) 651 secdata->flags |= AUTH_F_TRYNONE; 652 653 /* 654 * Failover support: 655 * 656 * We may have a linked list of nfs_args structures, 657 * which means the user is looking for failover. If 658 * the mount is either not "read-only" or "soft", 659 * we want to bail out with EINVAL. 660 */ 661 if (STRUCT_FGET(args, nfs_args_ext) == NFS_ARGS_EXTB && 662 STRUCT_FGETP(args, nfs_ext_u.nfs_extB.next) != NULL) { 663 if (uap->flags & MS_RDONLY && !(flags & NFSMNT_SOFT)) { 664 data = (char *)STRUCT_FGETP(args, 665 nfs_ext_u.nfs_extB.next); 666 goto more; 667 } 668 error = EINVAL; 669 goto errout; 670 } 671 672 /* 673 * Determine the zone we're being mounted into. 674 */ 675 zone_hold(mntzone = zone); /* start with this assumption */ 676 if (getzoneid() == GLOBAL_ZONEID) { 677 zone_rele(mntzone); 678 mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt)); 679 ASSERT(mntzone != NULL); 680 if (mntzone != zone) { 681 error = EBUSY; 682 goto errout; 683 } 684 } 685 686 if (is_system_labeled()) { 687 error = nfs_mount_label_policy(vfsp, &svp->sv_addr, 688 svp->sv_knconf, cr); 689 690 if (error > 0) 691 goto errout; 692 693 if (error == -1) { 694 /* change mount to read-only to prevent write-down */ 695 vfs_setmntopt(vfsp, MNTOPT_RO, NULL, 0); 696 } 697 } 698 699 /* 700 * Stop the mount from going any further if the zone is going away. 701 */ 702 if (zone_status_get(mntzone) >= ZONE_IS_SHUTTING_DOWN) { 703 error = EBUSY; 704 goto errout; 705 } 706 707 /* 708 * Get root vnode. 709 */ 710 proceed: 711 error = nfsrootvp(&rtvp, vfsp, svp_head, flags, cr, mntzone); 712 713 if (error) 714 goto errout; 715 716 /* 717 * Set option fields in the mount info record 718 */ 719 mi = VTOMI(rtvp); 720 721 if (svp_head->sv_next) 722 mi->mi_flags |= MI_LLOCK; 723 724 error = nfs_setopts(rtvp, get_udatamodel(), STRUCT_BUF(args)); 725 if (!error) { 726 /* static pathconf kludge */ 727 error = pathconf_get(mi, get_udatamodel(), STRUCT_BUF(args)); 728 } 729 730 errout: 731 if (error) { 732 if (rtvp != NULL) { 733 rp = VTOR(rtvp); 734 if (rp->r_flags & RHASHED) 735 rp_rmhash(rp); 736 } 737 sv_free(svp_head); 738 if (mi != NULL) { 739 nfs_async_stop(vfsp); 740 nfs_async_manager_stop(vfsp); 741 if (mi->mi_io_kstats) { 742 kstat_delete(mi->mi_io_kstats); 743 mi->mi_io_kstats = NULL; 744 } 745 if (mi->mi_ro_kstats) { 746 kstat_delete(mi->mi_ro_kstats); 747 mi->mi_ro_kstats = NULL; 748 } 749 nfs_free_mi(mi); 750 } 751 } 752 753 if (rtvp != NULL) 754 VN_RELE(rtvp); 755 756 if (mntzone != NULL) 757 zone_rele(mntzone); 758 759 return (error); 760 } 761 762 /* 763 * The pathconf information is kept on a linked list of kmem_alloc'ed 764 * structs. We search the list & add a new struct iff there is no other 765 * struct with the same information. 766 * See sys/pathconf.h for ``the rest of the story.'' 767 */ 768 static struct pathcnf *allpc = NULL; 769 770 static int 771 pathconf_get(struct mntinfo *mi, model_t model, struct nfs_args *args) 772 { 773 struct pathcnf *p; 774 struct pathcnf pc; 775 STRUCT_DECL(pathcnf, pc_tmp); 776 STRUCT_HANDLE(nfs_args, ap); 777 int i; 778 779 #ifdef lint 780 model = model; 781 #endif 782 783 STRUCT_INIT(pc_tmp, model); 784 STRUCT_SET_HANDLE(ap, model, args); 785 786 if (mi->mi_pathconf != NULL) { 787 pathconf_rele(mi); 788 mi->mi_pathconf = NULL; 789 } 790 if ((STRUCT_FGET(ap, flags) & NFSMNT_POSIX) && 791 STRUCT_FGETP(ap, pathconf) != NULL) { 792 if (copyin(STRUCT_FGETP(ap, pathconf), STRUCT_BUF(pc_tmp), 793 STRUCT_SIZE(pc_tmp))) 794 return (EFAULT); 795 if (_PC_ISSET(_PC_ERROR, STRUCT_FGET(pc_tmp, pc_mask))) 796 return (EINVAL); 797 798 pc.pc_link_max = STRUCT_FGET(pc_tmp, pc_link_max); 799 pc.pc_max_canon = STRUCT_FGET(pc_tmp, pc_max_canon); 800 pc.pc_max_input = STRUCT_FGET(pc_tmp, pc_max_input); 801 pc.pc_name_max = STRUCT_FGET(pc_tmp, pc_name_max); 802 pc.pc_path_max = STRUCT_FGET(pc_tmp, pc_path_max); 803 pc.pc_pipe_buf = STRUCT_FGET(pc_tmp, pc_pipe_buf); 804 pc.pc_vdisable = STRUCT_FGET(pc_tmp, pc_vdisable); 805 pc.pc_xxx = STRUCT_FGET(pc_tmp, pc_xxx); 806 for (i = 0; i < _PC_N; i++) 807 pc.pc_mask[i] = STRUCT_FGET(pc_tmp, pc_mask[i]); 808 809 for (p = allpc; p != NULL; p = p->pc_next) { 810 if (PCCMP(p, &pc) == 0) 811 break; 812 } 813 if (p != NULL) { 814 mi->mi_pathconf = p; 815 p->pc_refcnt++; 816 } else { 817 p = kmem_alloc(sizeof (*p), KM_SLEEP); 818 *p = pc; 819 p->pc_next = allpc; 820 p->pc_refcnt = 1; 821 allpc = mi->mi_pathconf = p; 822 } 823 } 824 return (0); 825 } 826 827 /* 828 * release the static pathconf information 829 */ 830 static void 831 pathconf_rele(struct mntinfo *mi) 832 { 833 if (mi->mi_pathconf != NULL) { 834 if (--mi->mi_pathconf->pc_refcnt == 0) { 835 struct pathcnf *p; 836 struct pathcnf *p2; 837 838 p2 = p = allpc; 839 while (p != NULL && p != mi->mi_pathconf) { 840 p2 = p; 841 p = p->pc_next; 842 } 843 if (p == NULL) { 844 panic("mi->pathconf"); 845 /*NOTREACHED*/ 846 } 847 if (p == allpc) 848 allpc = p->pc_next; 849 else 850 p2->pc_next = p->pc_next; 851 kmem_free(p, sizeof (*p)); 852 mi->mi_pathconf = NULL; 853 } 854 } 855 } 856 857 static int nfs_dynamic = 1; /* global variable to enable dynamic retrans. */ 858 static ushort_t nfs_max_threads = 8; /* max number of active async threads */ 859 static uint_t nfs_async_clusters = 1; /* # of reqs from each async queue */ 860 static uint_t nfs_cots_timeo = NFS_COTS_TIMEO; 861 862 static int 863 nfsrootvp(vnode_t **rtvpp, vfs_t *vfsp, struct servinfo *svp, 864 int flags, cred_t *cr, zone_t *zone) 865 { 866 vnode_t *rtvp; 867 mntinfo_t *mi; 868 dev_t nfs_dev; 869 struct vattr va; 870 int error; 871 rnode_t *rp; 872 int i; 873 struct nfs_stats *nfsstatsp; 874 cred_t *lcr = NULL, *tcr = cr; 875 876 nfsstatsp = zone_getspecific(nfsstat_zone_key, nfs_zone()); 877 ASSERT(nfsstatsp != NULL); 878 879 /* 880 * Create a mount record and link it to the vfs struct. 881 */ 882 mi = kmem_zalloc(sizeof (*mi), KM_SLEEP); 883 mutex_init(&mi->mi_lock, NULL, MUTEX_DEFAULT, NULL); 884 mutex_init(&mi->mi_remap_lock, NULL, MUTEX_DEFAULT, NULL); 885 mi->mi_flags = MI_ACL | MI_EXTATTR; 886 if (!(flags & NFSMNT_SOFT)) 887 mi->mi_flags |= MI_HARD; 888 if ((flags & NFSMNT_SEMISOFT)) 889 mi->mi_flags |= MI_SEMISOFT; 890 if ((flags & NFSMNT_NOPRINT)) 891 mi->mi_flags |= MI_NOPRINT; 892 if (flags & NFSMNT_INT) 893 mi->mi_flags |= MI_INT; 894 mi->mi_retrans = NFS_RETRIES; 895 if (svp->sv_knconf->knc_semantics == NC_TPI_COTS_ORD || 896 svp->sv_knconf->knc_semantics == NC_TPI_COTS) 897 mi->mi_timeo = nfs_cots_timeo; 898 else 899 mi->mi_timeo = NFS_TIMEO; 900 mi->mi_prog = NFS_PROGRAM; 901 mi->mi_vers = NFS_VERSION; 902 mi->mi_rfsnames = rfsnames_v2; 903 mi->mi_reqs = nfsstatsp->nfs_stats_v2.rfsreqcnt_ptr; 904 mi->mi_call_type = call_type_v2; 905 mi->mi_ss_call_type = ss_call_type_v2; 906 mi->mi_timer_type = timer_type_v2; 907 mi->mi_aclnames = aclnames_v2; 908 mi->mi_aclreqs = nfsstatsp->nfs_stats_v2.aclreqcnt_ptr; 909 mi->mi_acl_call_type = acl_call_type_v2; 910 mi->mi_acl_ss_call_type = acl_ss_call_type_v2; 911 mi->mi_acl_timer_type = acl_timer_type_v2; 912 cv_init(&mi->mi_failover_cv, NULL, CV_DEFAULT, NULL); 913 mi->mi_servers = svp; 914 mi->mi_curr_serv = svp; 915 mi->mi_acregmin = SEC2HR(ACREGMIN); 916 mi->mi_acregmax = SEC2HR(ACREGMAX); 917 mi->mi_acdirmin = SEC2HR(ACDIRMIN); 918 mi->mi_acdirmax = SEC2HR(ACDIRMAX); 919 920 if (nfs_dynamic) 921 mi->mi_flags |= MI_DYNAMIC; 922 923 if (flags & NFSMNT_DIRECTIO) 924 mi->mi_flags |= MI_DIRECTIO; 925 926 /* 927 * Make a vfs struct for nfs. We do this here instead of below 928 * because rtvp needs a vfs before we can do a getattr on it. 929 * 930 * Assign a unique device id to the mount 931 */ 932 mutex_enter(&nfs_minor_lock); 933 do { 934 nfs_minor = (nfs_minor + 1) & MAXMIN32; 935 nfs_dev = makedevice(nfs_major, nfs_minor); 936 } while (vfs_devismounted(nfs_dev)); 937 mutex_exit(&nfs_minor_lock); 938 939 vfsp->vfs_dev = nfs_dev; 940 vfs_make_fsid(&vfsp->vfs_fsid, nfs_dev, nfsfstyp); 941 vfsp->vfs_data = (caddr_t)mi; 942 vfsp->vfs_fstype = nfsfstyp; 943 vfsp->vfs_bsize = NFS_MAXDATA; 944 945 /* 946 * Initialize fields used to support async putpage operations. 947 */ 948 for (i = 0; i < NFS_ASYNC_TYPES; i++) 949 mi->mi_async_clusters[i] = nfs_async_clusters; 950 mi->mi_async_init_clusters = nfs_async_clusters; 951 mi->mi_async_curr = &mi->mi_async_reqs[0]; 952 mi->mi_max_threads = nfs_max_threads; 953 mutex_init(&mi->mi_async_lock, NULL, MUTEX_DEFAULT, NULL); 954 cv_init(&mi->mi_async_reqs_cv, NULL, CV_DEFAULT, NULL); 955 cv_init(&mi->mi_async_work_cv, NULL, CV_DEFAULT, NULL); 956 cv_init(&mi->mi_async_cv, NULL, CV_DEFAULT, NULL); 957 958 mi->mi_vfsp = vfsp; 959 zone_hold(mi->mi_zone = zone); 960 nfs_mi_zonelist_add(mi); 961 962 /* 963 * Make the root vnode, use it to get attributes, 964 * then remake it with the attributes. 965 */ 966 rtvp = makenfsnode((fhandle_t *)svp->sv_fhandle.fh_buf, 967 NULL, vfsp, gethrtime(), cr, NULL, NULL); 968 969 va.va_mask = AT_ALL; 970 971 /* 972 * If the uid is set then set the creds for secure mounts 973 * by proxy processes such as automountd. 974 */ 975 if (svp->sv_secdata->uid != 0 && 976 svp->sv_secdata->rpcflavor == RPCSEC_GSS) { 977 lcr = crdup(cr); 978 (void) crsetugid(lcr, svp->sv_secdata->uid, crgetgid(cr)); 979 tcr = lcr; 980 } 981 982 error = nfsgetattr(rtvp, &va, tcr); 983 if (error) 984 goto bad; 985 rtvp->v_type = va.va_type; 986 987 /* 988 * Poll every server to get the filesystem stats; we're 989 * only interested in the server's transfer size, and we 990 * want the minimum. 991 * 992 * While we're looping, we'll turn off AUTH_F_TRYNONE, 993 * which is only for the mount operation. 994 */ 995 996 mi->mi_tsize = MIN(NFS_MAXDATA, nfstsize()); 997 mi->mi_stsize = MIN(NFS_MAXDATA, nfstsize()); 998 999 for (svp = mi->mi_servers; svp != NULL; svp = svp->sv_next) { 1000 struct nfsstatfs fs; 1001 int douprintf; 1002 1003 douprintf = 1; 1004 mi->mi_curr_serv = svp; 1005 1006 error = rfs2call(mi, RFS_STATFS, 1007 xdr_fhandle, (caddr_t)svp->sv_fhandle.fh_buf, 1008 xdr_statfs, (caddr_t)&fs, tcr, &douprintf, 1009 &fs.fs_status, 0, NULL); 1010 if (error) 1011 goto bad; 1012 mi->mi_stsize = MIN(mi->mi_stsize, fs.fs_tsize); 1013 svp->sv_secdata->flags &= ~AUTH_F_TRYNONE; 1014 } 1015 mi->mi_curr_serv = mi->mi_servers; 1016 mi->mi_curread = mi->mi_tsize; 1017 mi->mi_curwrite = mi->mi_stsize; 1018 1019 /* 1020 * Start the manager thread responsible for handling async worker 1021 * threads. 1022 */ 1023 VFS_HOLD(vfsp); /* add reference for thread */ 1024 mi->mi_manager_thread = zthread_create(NULL, 0, nfs_async_manager, 1025 vfsp, 0, minclsyspri); 1026 ASSERT(mi->mi_manager_thread != NULL); 1027 1028 /* 1029 * Initialize kstats 1030 */ 1031 nfs_mnt_kstat_init(vfsp); 1032 1033 mi->mi_type = rtvp->v_type; 1034 1035 *rtvpp = rtvp; 1036 if (lcr != NULL) 1037 crfree(lcr); 1038 1039 return (0); 1040 bad: 1041 /* 1042 * An error occurred somewhere, need to clean up... 1043 * We need to release our reference to the root vnode and 1044 * destroy the mntinfo struct that we just created. 1045 */ 1046 if (lcr != NULL) 1047 crfree(lcr); 1048 rp = VTOR(rtvp); 1049 if (rp->r_flags & RHASHED) 1050 rp_rmhash(rp); 1051 VN_RELE(rtvp); 1052 nfs_async_stop(vfsp); 1053 nfs_async_manager_stop(vfsp); 1054 if (mi->mi_io_kstats) { 1055 kstat_delete(mi->mi_io_kstats); 1056 mi->mi_io_kstats = NULL; 1057 } 1058 if (mi->mi_ro_kstats) { 1059 kstat_delete(mi->mi_ro_kstats); 1060 mi->mi_ro_kstats = NULL; 1061 } 1062 nfs_free_mi(mi); 1063 *rtvpp = NULL; 1064 return (error); 1065 } 1066 1067 /* 1068 * vfs operations 1069 */ 1070 static int 1071 nfs_unmount(vfs_t *vfsp, int flag, cred_t *cr) 1072 { 1073 mntinfo_t *mi; 1074 ushort_t omax; 1075 1076 if (secpolicy_fs_unmount(cr, vfsp) != 0) 1077 return (EPERM); 1078 1079 mi = VFTOMI(vfsp); 1080 if (flag & MS_FORCE) { 1081 vfsp->vfs_flag |= VFS_UNMOUNTED; 1082 /* 1083 * We need to stop the manager thread explicitly; the worker 1084 * threads can time out and exit on their own. 1085 */ 1086 nfs_async_manager_stop(vfsp); 1087 destroy_rtable(vfsp, cr); 1088 if (mi->mi_io_kstats) { 1089 kstat_delete(mi->mi_io_kstats); 1090 mi->mi_io_kstats = NULL; 1091 } 1092 if (mi->mi_ro_kstats) { 1093 kstat_delete(mi->mi_ro_kstats); 1094 mi->mi_ro_kstats = NULL; 1095 } 1096 return (0); 1097 } 1098 /* 1099 * Wait until all asynchronous putpage operations on 1100 * this file system are complete before flushing rnodes 1101 * from the cache. 1102 */ 1103 omax = mi->mi_max_threads; 1104 if (nfs_async_stop_sig(vfsp)) { 1105 return (EINTR); 1106 } 1107 rflush(vfsp, cr); 1108 /* 1109 * If there are any active vnodes on this file system, 1110 * then the file system is busy and can't be umounted. 1111 */ 1112 if (check_rtable(vfsp)) { 1113 mutex_enter(&mi->mi_async_lock); 1114 mi->mi_max_threads = omax; 1115 mutex_exit(&mi->mi_async_lock); 1116 return (EBUSY); 1117 } 1118 /* 1119 * The unmount can't fail from now on; stop the manager thread. 1120 */ 1121 nfs_async_manager_stop(vfsp); 1122 /* 1123 * Destroy all rnodes belonging to this file system from the 1124 * rnode hash queues and purge any resources allocated to 1125 * them. 1126 */ 1127 destroy_rtable(vfsp, cr); 1128 if (mi->mi_io_kstats) { 1129 kstat_delete(mi->mi_io_kstats); 1130 mi->mi_io_kstats = NULL; 1131 } 1132 if (mi->mi_ro_kstats) { 1133 kstat_delete(mi->mi_ro_kstats); 1134 mi->mi_ro_kstats = NULL; 1135 } 1136 return (0); 1137 } 1138 1139 /* 1140 * find root of nfs 1141 */ 1142 static int 1143 nfs_root(vfs_t *vfsp, vnode_t **vpp) 1144 { 1145 mntinfo_t *mi; 1146 vnode_t *vp; 1147 servinfo_t *svp; 1148 1149 mi = VFTOMI(vfsp); 1150 1151 if (nfs_zone() != mi->mi_zone) 1152 return (EPERM); 1153 1154 svp = mi->mi_curr_serv; 1155 if (svp && (svp->sv_flags & SV_ROOT_STALE)) { 1156 mutex_enter(&svp->sv_lock); 1157 svp->sv_flags &= ~SV_ROOT_STALE; 1158 mutex_exit(&svp->sv_lock); 1159 return (ENOENT); 1160 } 1161 1162 vp = makenfsnode((fhandle_t *)mi->mi_curr_serv->sv_fhandle.fh_buf, 1163 NULL, vfsp, gethrtime(), CRED(), NULL, NULL); 1164 1165 if (VTOR(vp)->r_flags & RSTALE) { 1166 VN_RELE(vp); 1167 return (ENOENT); 1168 } 1169 1170 ASSERT(vp->v_type == VNON || vp->v_type == mi->mi_type); 1171 1172 vp->v_type = mi->mi_type; 1173 1174 *vpp = vp; 1175 1176 return (0); 1177 } 1178 1179 /* 1180 * Get file system statistics. 1181 */ 1182 static int 1183 nfs_statvfs(vfs_t *vfsp, struct statvfs64 *sbp) 1184 { 1185 int error; 1186 mntinfo_t *mi; 1187 struct nfsstatfs fs; 1188 int douprintf; 1189 failinfo_t fi; 1190 vnode_t *vp; 1191 1192 error = nfs_root(vfsp, &vp); 1193 if (error) 1194 return (error); 1195 1196 mi = VFTOMI(vfsp); 1197 douprintf = 1; 1198 fi.vp = vp; 1199 fi.fhp = NULL; /* no need to update, filehandle not copied */ 1200 fi.copyproc = nfscopyfh; 1201 fi.lookupproc = nfslookup; 1202 fi.xattrdirproc = acl_getxattrdir2; 1203 1204 error = rfs2call(mi, RFS_STATFS, 1205 xdr_fhandle, (caddr_t)VTOFH(vp), 1206 xdr_statfs, (caddr_t)&fs, CRED(), &douprintf, 1207 &fs.fs_status, 0, &fi); 1208 1209 if (!error) { 1210 error = geterrno(fs.fs_status); 1211 if (!error) { 1212 mutex_enter(&mi->mi_lock); 1213 if (mi->mi_stsize) { 1214 mi->mi_stsize = MIN(mi->mi_stsize, fs.fs_tsize); 1215 } else { 1216 mi->mi_stsize = fs.fs_tsize; 1217 mi->mi_curwrite = mi->mi_stsize; 1218 } 1219 mutex_exit(&mi->mi_lock); 1220 sbp->f_bsize = fs.fs_bsize; 1221 sbp->f_frsize = fs.fs_bsize; 1222 sbp->f_blocks = (fsblkcnt64_t)fs.fs_blocks; 1223 sbp->f_bfree = (fsblkcnt64_t)fs.fs_bfree; 1224 /* 1225 * Some servers may return negative available 1226 * block counts. They may do this because they 1227 * calculate the number of available blocks by 1228 * subtracting the number of used blocks from 1229 * the total number of blocks modified by the 1230 * minimum free value. For example, if the 1231 * minumum free percentage is 10 and the file 1232 * system is greater than 90 percent full, then 1233 * 90 percent of the total blocks minus the 1234 * actual number of used blocks may be a 1235 * negative number. 1236 * 1237 * In this case, we need to sign extend the 1238 * negative number through the assignment from 1239 * the 32 bit bavail count to the 64 bit bavail 1240 * count. 1241 * 1242 * We need to be able to discern between there 1243 * just being a lot of available blocks on the 1244 * file system and the case described above. 1245 * We are making the assumption that it does 1246 * not make sense to have more available blocks 1247 * than there are free blocks. So, if there 1248 * are, then we treat the number as if it were 1249 * a negative number and arrange to have it 1250 * sign extended when it is converted from 32 1251 * bits to 64 bits. 1252 */ 1253 if (fs.fs_bavail <= fs.fs_bfree) 1254 sbp->f_bavail = (fsblkcnt64_t)fs.fs_bavail; 1255 else { 1256 sbp->f_bavail = 1257 (fsblkcnt64_t)((long)fs.fs_bavail); 1258 } 1259 sbp->f_files = (fsfilcnt64_t)-1; 1260 sbp->f_ffree = (fsfilcnt64_t)-1; 1261 sbp->f_favail = (fsfilcnt64_t)-1; 1262 sbp->f_fsid = (unsigned long)vfsp->vfs_fsid.val[0]; 1263 (void) strncpy(sbp->f_basetype, 1264 vfssw[vfsp->vfs_fstype].vsw_name, FSTYPSZ); 1265 sbp->f_flag = vf_to_stf(vfsp->vfs_flag); 1266 sbp->f_namemax = (uint32_t)-1; 1267 } else { 1268 PURGE_STALE_FH(error, vp, CRED()); 1269 } 1270 } 1271 1272 VN_RELE(vp); 1273 1274 return (error); 1275 } 1276 1277 static kmutex_t nfs_syncbusy; 1278 1279 /* 1280 * Flush dirty nfs files for file system vfsp. 1281 * If vfsp == NULL, all nfs files are flushed. 1282 */ 1283 /* ARGSUSED */ 1284 static int 1285 nfs_sync(vfs_t *vfsp, short flag, cred_t *cr) 1286 { 1287 /* 1288 * Cross-zone calls are OK here, since this translates to a 1289 * VOP_PUTPAGE(B_ASYNC), which gets picked up by the right zone. 1290 */ 1291 if (!(flag & SYNC_ATTR) && mutex_tryenter(&nfs_syncbusy) != 0) { 1292 rflush(vfsp, cr); 1293 mutex_exit(&nfs_syncbusy); 1294 } 1295 return (0); 1296 } 1297 1298 /* ARGSUSED */ 1299 static int 1300 nfs_vget(vfs_t *vfsp, vnode_t **vpp, fid_t *fidp) 1301 { 1302 int error; 1303 vnode_t *vp; 1304 struct vattr va; 1305 struct nfs_fid *nfsfidp = (struct nfs_fid *)fidp; 1306 zoneid_t zoneid = VFTOMI(vfsp)->mi_zone->zone_id; 1307 1308 if (nfs_zone() != VFTOMI(vfsp)->mi_zone) 1309 return (EPERM); 1310 if (fidp->fid_len != (sizeof (*nfsfidp) - sizeof (short))) { 1311 #ifdef DEBUG 1312 zcmn_err(zoneid, CE_WARN, 1313 "nfs_vget: bad fid len, %d/%d", fidp->fid_len, 1314 (int)(sizeof (*nfsfidp) - sizeof (short))); 1315 #endif 1316 *vpp = NULL; 1317 return (ESTALE); 1318 } 1319 1320 vp = makenfsnode((fhandle_t *)(nfsfidp->nf_data), NULL, vfsp, 1321 gethrtime(), CRED(), NULL, NULL); 1322 1323 if (VTOR(vp)->r_flags & RSTALE) { 1324 VN_RELE(vp); 1325 *vpp = NULL; 1326 return (ENOENT); 1327 } 1328 1329 if (vp->v_type == VNON) { 1330 va.va_mask = AT_ALL; 1331 error = nfsgetattr(vp, &va, CRED()); 1332 if (error) { 1333 VN_RELE(vp); 1334 *vpp = NULL; 1335 return (error); 1336 } 1337 vp->v_type = va.va_type; 1338 } 1339 1340 *vpp = vp; 1341 1342 return (0); 1343 } 1344 1345 /* ARGSUSED */ 1346 static int 1347 nfs_mountroot(vfs_t *vfsp, whymountroot_t why) 1348 { 1349 vnode_t *rtvp; 1350 char root_hostname[SYS_NMLN+1]; 1351 struct servinfo *svp; 1352 int error; 1353 int vfsflags; 1354 size_t size; 1355 char *root_path; 1356 struct pathname pn; 1357 char *name; 1358 cred_t *cr; 1359 struct nfs_args args; /* nfs mount arguments */ 1360 static char token[10]; 1361 1362 bzero(&args, sizeof (args)); 1363 1364 /* do this BEFORE getfile which causes xid stamps to be initialized */ 1365 clkset(-1L); /* hack for now - until we get time svc? */ 1366 1367 if (why == ROOT_REMOUNT) { 1368 /* 1369 * Shouldn't happen. 1370 */ 1371 panic("nfs_mountroot: why == ROOT_REMOUNT"); 1372 } 1373 1374 if (why == ROOT_UNMOUNT) { 1375 /* 1376 * Nothing to do for NFS. 1377 */ 1378 return (0); 1379 } 1380 1381 /* 1382 * why == ROOT_INIT 1383 */ 1384 1385 name = token; 1386 *name = 0; 1387 getfsname("root", name, sizeof (token)); 1388 1389 pn_alloc(&pn); 1390 root_path = pn.pn_path; 1391 1392 svp = kmem_zalloc(sizeof (*svp), KM_SLEEP); 1393 svp->sv_knconf = kmem_zalloc(sizeof (*svp->sv_knconf), KM_SLEEP); 1394 svp->sv_knconf->knc_protofmly = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 1395 svp->sv_knconf->knc_proto = kmem_alloc(KNC_STRSIZE, KM_SLEEP); 1396 1397 /* 1398 * Get server address 1399 * Get the root fhandle 1400 * Get server's transport 1401 * Get server's hostname 1402 * Get options 1403 */ 1404 args.addr = &svp->sv_addr; 1405 args.fh = (char *)&svp->sv_fhandle.fh_buf; 1406 args.knconf = svp->sv_knconf; 1407 args.hostname = root_hostname; 1408 vfsflags = 0; 1409 if (error = mount_root(*name ? name : "root", root_path, NFS_VERSION, 1410 &args, &vfsflags)) { 1411 nfs_cmn_err(error, CE_WARN, 1412 "nfs_mountroot: mount_root failed: %m"); 1413 sv_free(svp); 1414 pn_free(&pn); 1415 return (error); 1416 } 1417 svp->sv_fhandle.fh_len = NFS_FHSIZE; 1418 svp->sv_hostnamelen = (int)(strlen(root_hostname) + 1); 1419 svp->sv_hostname = kmem_alloc(svp->sv_hostnamelen, KM_SLEEP); 1420 (void) strcpy(svp->sv_hostname, root_hostname); 1421 1422 /* 1423 * Force root partition to always be mounted with AUTH_UNIX for now 1424 */ 1425 svp->sv_secdata = kmem_alloc(sizeof (*svp->sv_secdata), KM_SLEEP); 1426 svp->sv_secdata->secmod = AUTH_UNIX; 1427 svp->sv_secdata->rpcflavor = AUTH_UNIX; 1428 svp->sv_secdata->data = NULL; 1429 1430 cr = crgetcred(); 1431 rtvp = NULL; 1432 1433 error = nfsrootvp(&rtvp, vfsp, svp, args.flags, cr, global_zone); 1434 1435 crfree(cr); 1436 1437 if (error) { 1438 pn_free(&pn); 1439 goto errout; 1440 } 1441 1442 error = nfs_setopts(rtvp, DATAMODEL_NATIVE, &args); 1443 if (error) { 1444 nfs_cmn_err(error, CE_WARN, 1445 "nfs_mountroot: invalid root mount options"); 1446 pn_free(&pn); 1447 goto errout; 1448 } 1449 1450 (void) vfs_lock_wait(vfsp); 1451 vfs_add(NULL, vfsp, vfsflags); 1452 vfs_unlock(vfsp); 1453 1454 size = strlen(svp->sv_hostname); 1455 (void) strcpy(rootfs.bo_name, svp->sv_hostname); 1456 rootfs.bo_name[size] = ':'; 1457 (void) strcpy(&rootfs.bo_name[size + 1], root_path); 1458 1459 pn_free(&pn); 1460 1461 errout: 1462 if (error) { 1463 sv_free(svp); 1464 nfs_async_stop(vfsp); 1465 nfs_async_manager_stop(vfsp); 1466 } 1467 1468 if (rtvp != NULL) 1469 VN_RELE(rtvp); 1470 1471 return (error); 1472 } 1473 1474 /* 1475 * Initialization routine for VFS routines. Should only be called once 1476 */ 1477 int 1478 nfs_vfsinit(void) 1479 { 1480 mutex_init(&nfs_syncbusy, NULL, MUTEX_DEFAULT, NULL); 1481 return (0); 1482 } 1483 1484 void 1485 nfs_vfsfini(void) 1486 { 1487 mutex_destroy(&nfs_syncbusy); 1488 } 1489 1490 void 1491 nfs_freevfs(vfs_t *vfsp) 1492 { 1493 mntinfo_t *mi; 1494 servinfo_t *svp; 1495 1496 /* free up the resources */ 1497 mi = VFTOMI(vfsp); 1498 pathconf_rele(mi); 1499 svp = mi->mi_servers; 1500 mi->mi_servers = mi->mi_curr_serv = NULL; 1501 sv_free(svp); 1502 1503 /* 1504 * By this time we should have already deleted the 1505 * mi kstats in the unmount code. If they are still around 1506 * somethings wrong 1507 */ 1508 ASSERT(mi->mi_io_kstats == NULL); 1509 nfs_free_mi(mi); 1510 } 1511