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