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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/cred.h> 32 #include <sys/proc.h> 33 #include <sys/user.h> 34 #include <sys/vfs.h> 35 #include <sys/vfs_opreg.h> 36 #include <sys/vnode.h> 37 #include <sys/pathname.h> 38 #include <sys/uio.h> 39 #include <sys/tiuser.h> 40 #include <sys/sysmacros.h> 41 #include <sys/kmem.h> 42 #include <sys/mount.h> 43 #include <sys/ioctl.h> 44 #include <sys/statvfs.h> 45 #include <sys/stat.h> 46 #include <sys/errno.h> 47 #include <sys/debug.h> 48 #include <sys/cmn_err.h> 49 #include <sys/utsname.h> 50 #include <sys/bootconf.h> 51 #include <sys/reboot.h> 52 #include <sys/modctl.h> 53 #include <rpc/types.h> 54 55 #include <sys/fs/cachefs_fs.h> 56 #include <sys/fs/cachefs_log.h> 57 #include <sys/mkdev.h> 58 #include <sys/dnlc.h> 59 #include <sys/policy.h> 60 #include "fs/fs_subr.h" 61 62 extern kmutex_t cachefs_kmem_lock; 63 kmutex_t cachefs_kstat_key_lock; 64 65 /* forward declarations */ 66 static int cachefs_remount(struct vfs *, struct mounta *); 67 static void cachefs_delete_cachep(cachefscache_t *); 68 69 #define CFS_MAPSIZE 256 70 71 kmutex_t cachefs_cachelock; /* Cache list mutex */ 72 cachefscache_t *cachefs_cachelist = NULL; /* Cache struct list */ 73 74 int cachefs_mount_retries = 3; 75 kmutex_t cachefs_minor_lock; /* Lock for minor device map */ 76 major_t cachefs_major = 0; 77 minor_t cachefs_minor = 0; 78 cachefs_kstat_key_t *cachefs_kstat_key = NULL; 79 int cachefs_kstat_key_n = 0; 80 static uint32_t cachefs_nfsv4_warnmsg = FALSE; 81 82 /* 83 * cachefs vfs operations. 84 */ 85 static int cachefs_mount(vfs_t *, vnode_t *, struct mounta *, cred_t *); 86 static int cachefs_unmount(vfs_t *, int, cred_t *); 87 static int cachefs_root(vfs_t *, vnode_t **); 88 static int cachefs_statvfs(register vfs_t *, struct statvfs64 *); 89 static int cachefs_sync(vfs_t *, short, cred_t *); 90 91 /* 92 * Initialize the vfs structure 93 */ 94 int cachefsfstyp; 95 int cnodesize = 0; 96 97 int 98 cachefs_init_vfsops(int fstype) 99 { 100 static const fs_operation_def_t cachefs_vfsops_template[] = { 101 VFSNAME_MOUNT, { .vfs_mount = cachefs_mount }, 102 VFSNAME_UNMOUNT, { .vfs_unmount = cachefs_unmount }, 103 VFSNAME_ROOT, { .vfs_root = cachefs_root }, 104 VFSNAME_STATVFS, { .vfs_statvfs = cachefs_statvfs }, 105 VFSNAME_SYNC, { .vfs_sync = cachefs_sync }, 106 NULL, NULL 107 }; 108 int error; 109 110 error = vfs_setfsops(fstype, cachefs_vfsops_template, NULL); 111 if (error != 0) 112 return (error); 113 114 cachefsfstyp = fstype; 115 116 return (0); 117 } 118 119 dev_t 120 cachefs_mkmntdev(void) 121 { 122 dev_t cachefs_dev; 123 124 mutex_enter(&cachefs_minor_lock); 125 do { 126 cachefs_minor = (cachefs_minor + 1) & MAXMIN32; 127 cachefs_dev = makedevice(cachefs_major, cachefs_minor); 128 } while (vfs_devismounted(cachefs_dev)); 129 mutex_exit(&cachefs_minor_lock); 130 131 return (cachefs_dev); 132 } 133 134 /* 135 * vfs operations 136 */ 137 static int 138 cachefs_mount(vfs_t *vfsp, vnode_t *mvp, struct mounta *uap, cred_t *cr) 139 { 140 char *data = uap->dataptr; 141 STRUCT_DECL(cachefs_mountargs, map); 142 struct cachefsoptions *cfs_options; 143 char *backfs, *cacheid, *cachedir; 144 vnode_t *cachedirvp = NULL; 145 vnode_t *backrootvp = NULL; 146 cachefscache_t *cachep = NULL; 147 fscache_t *fscp = NULL; 148 cnode_t *cp; 149 struct fid *cookiep = NULL; 150 struct vattr *attrp = NULL; 151 dev_t cachefs_dev; /* devid for this mount */ 152 int error = 0; 153 int retries = cachefs_mount_retries; 154 ino64_t fsid; 155 cfs_cid_t cid; 156 char *backmntpt; 157 ino64_t backfileno; 158 struct vfs *backvfsp; 159 size_t strl; 160 char tmpstr[MAXPATHLEN]; 161 vnode_t *tmpdirvp = NULL; 162 ulong_t maxfilesizebits; 163 uint32_t valid_fid; 164 165 #ifdef CFSDEBUG 166 CFS_DEBUG(CFSDEBUG_VFSOP) 167 printf("cachefs_mount: ENTER cachefs_mntargs %p\n", data); 168 #endif 169 170 /* 171 * Make sure we have sufficient privileges. 172 */ 173 if ((error = secpolicy_fs_mount(cr, mvp, vfsp)) != 0) 174 goto out; 175 176 /* 177 * make sure we're mounting on a directory 178 */ 179 if (mvp->v_type != VDIR) { 180 error = ENOTDIR; 181 goto out; 182 } 183 184 /* 185 * Determine the zone we're being mounted into, and make sure it's the 186 * global zone. 187 */ 188 if (getzoneid() == GLOBAL_ZONEID) { 189 zone_t *mntzone; 190 191 mntzone = zone_find_by_path(refstr_value(vfsp->vfs_mntpt)); 192 ASSERT(mntzone != NULL); 193 zone_rele(mntzone); 194 if (mntzone != curproc->p_zone) { 195 error = EBUSY; 196 goto out; 197 } 198 } else { 199 error = EPERM; 200 goto out; 201 } 202 203 if (uap->flags & MS_REMOUNT) { 204 error = cachefs_remount(vfsp, uap); 205 goto out; 206 } 207 208 /* 209 * Assign a unique device id to the mount 210 */ 211 cachefs_dev = cachefs_mkmntdev(); 212 #ifdef _LP64 213 /* 214 * It's not a good idea to make fsid bigger since that'll 215 * have adverse effects on nfs filehandles. For now assume that 216 * cachefs be used on devices that fit into dev32_t's. 217 */ 218 if (cachefs_dev == NODEV) { 219 error = EOVERFLOW; 220 goto out; 221 } 222 #endif 223 224 /* 225 * Copy in the arguments 226 */ 227 STRUCT_INIT(map, get_udatamodel()); 228 error = copyin(data, STRUCT_BUF(map), 229 SIZEOF_STRUCT(cachefs_mountargs, DATAMODEL_NATIVE)); 230 if (error) { 231 goto out; 232 } 233 234 cfs_options = (struct cachefsoptions *)STRUCT_FADDR(map, cfs_options); 235 cacheid = (char *)STRUCT_FGETP(map, cfs_cacheid); 236 if ((cfs_options->opt_flags & 237 (CFS_WRITE_AROUND|CFS_NONSHARED|CFS_BACKFS_NFSV4)) == 0) { 238 error = EINVAL; 239 goto out; 240 } 241 if ((cfs_options->opt_popsize % MAXBSIZE) != 0) { 242 error = EINVAL; 243 goto out; 244 } 245 /* 246 * Get the cache directory vp 247 */ 248 /*LINTED 32-bit pointer casting okay*/ 249 cachedir = (char *)STRUCT_FGETP(map, cfs_cachedir); 250 error = lookupname(cachedir, UIO_USERSPACE, FOLLOW, 251 NULLVPP, &cachedirvp); 252 if (error) 253 goto out; 254 255 /* 256 * Make sure the thing we just looked up is a directory 257 */ 258 if (cachedirvp->v_type != VDIR) { 259 cmn_err(CE_WARN, "cachefs_mount: cachedir not a directory\n"); 260 error = EINVAL; 261 goto out; 262 } 263 264 /* 265 * Make sure the cache doesn't live in cachefs! 266 */ 267 if (vn_matchops(cachedirvp, cachefs_getvnodeops())) { 268 cmn_err(CE_WARN, "cachefs_mount: cachedir in cachefs!\n"); 269 error = EINVAL; 270 goto out; 271 } 272 273 /* if the backfs is mounted */ 274 /*LINTED 32-bit pointer casting okay*/ 275 if ((backfs = STRUCT_FGETP(map, cfs_backfs)) != NULL) { 276 /* 277 * Get the back file system root vp 278 */ 279 error = lookupname(backfs, UIO_USERSPACE, FOLLOW, 280 NULLVPP, &backrootvp); 281 if (error) 282 goto out; 283 284 /* 285 * Make sure the thing we just looked up is a directory 286 * and a root of a file system 287 */ 288 if (backrootvp->v_type != VDIR || 289 !(backrootvp->v_flag & VROOT)) { 290 cmn_err(CE_WARN, 291 "cachefs_mount: backpath not a directory\n"); 292 error = EINVAL; 293 goto out; 294 } 295 296 /* 297 * Get the fid and attributes for the root of the 298 * backfilesystem, except if NFSv4 is in use, 299 * in which case we get the attributes only (the 300 * (VOP_FID() operation called by cachefs_get_cookie() 301 * is not supported in NFSv4). 302 */ 303 cookiep = cachefs_kmem_alloc(sizeof (struct fid), KM_SLEEP); 304 attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP); 305 306 if ((cfs_options->opt_flags & CFS_BACKFS_NFSV4)) { 307 valid_fid = FALSE; 308 } else { 309 valid_fid = TRUE; 310 } 311 error = cachefs_getcookie(backrootvp, cookiep, attrp, cr, 312 valid_fid); 313 314 if (error) 315 goto out; 316 317 backmntpt = backfs; 318 backfileno = attrp->va_nodeid; 319 backvfsp = backrootvp->v_vfsp; 320 } else { 321 backmntpt = NULL; 322 backfileno = 0; 323 backvfsp = NULL; 324 } 325 326 again: 327 328 /* 329 * In SVR4 it's not acceptable to stack up mounts 330 * unless MS_OVERLAY specified. 331 */ 332 mutex_enter(&mvp->v_lock); 333 if (((uap->flags & MS_OVERLAY) == 0) && 334 ((mvp->v_count != 1) || (mvp->v_flag & VROOT))) { 335 mutex_exit(&mvp->v_lock); 336 error = EBUSY; 337 goto out; 338 } 339 mutex_exit(&mvp->v_lock); 340 341 /* 342 * Lock out other mounts and unmounts until we safely have 343 * a mounted fscache object. 344 */ 345 mutex_enter(&cachefs_cachelock); 346 347 /* 348 * Find the cache structure 349 */ 350 for (cachep = cachefs_cachelist; cachep != NULL; 351 cachep = cachep->c_next) { 352 if (cachep->c_dirvp == cachedirvp) 353 break; 354 } 355 356 /* if the cache object does not exist, then create it */ 357 if (cachep == NULL) { 358 cachep = cachefs_cache_create(); 359 error = cachefs_cache_activate_ro(cachep, cachedirvp); 360 if (error) { 361 cachefs_cache_destroy(cachep); 362 cachep = NULL; 363 goto out; 364 } 365 if ((cfs_options->opt_flags & CFS_NOFILL) == 0) 366 cachefs_cache_activate_rw(cachep); 367 else 368 cfs_options->opt_flags &= ~CFS_NOFILL; 369 370 cachep->c_next = cachefs_cachelist; 371 cachefs_cachelist = cachep; 372 } else if (cfs_options->opt_flags & CFS_NOFILL) { 373 cmn_err(CE_WARN, 374 "CacheFS: attempt to convert nonempty cache " 375 "to NOFILL mode"); 376 error = EINVAL; 377 goto out; 378 } 379 380 /* get the fscache id for this name */ 381 error = fscache_name_to_fsid(cachep, cacheid, &fsid); 382 if (error) { 383 fsid = 0; 384 } 385 386 /* find the fscache object for this mount point or create it */ 387 mutex_enter(&cachep->c_fslistlock); 388 fscp = fscache_list_find(cachep, fsid); 389 if (fscp == NULL) { 390 fscp = fscache_create(cachep); 391 error = fscache_activate(fscp, fsid, cacheid, 392 cfs_options, backfileno); 393 if (error) { 394 fscache_destroy(fscp); 395 fscp = NULL; 396 mutex_exit(&cachep->c_fslistlock); 397 if ((error == ENOSPC) && (retries-- > 0)) { 398 mutex_exit(&cachefs_cachelock); 399 delay(6 * hz); 400 goto again; 401 } 402 goto out; 403 } 404 fscache_list_add(cachep, fscp); 405 } else { 406 /* compare the options to make sure they are compatable */ 407 error = fscache_compare_options(fscp, cfs_options); 408 if (error) { 409 cmn_err(CE_WARN, 410 "CacheFS: mount failed, options do not match."); 411 fscp = NULL; 412 mutex_exit(&cachep->c_fslistlock); 413 goto out; 414 } 415 416 /* copy options into the fscache */ 417 mutex_enter(&fscp->fs_fslock); 418 fscp->fs_info.fi_mntflags = cfs_options->opt_flags; 419 fscp->fs_info.fi_popsize = cfs_options->opt_popsize; 420 fscp->fs_info.fi_fgsize = cfs_options->opt_fgsize; 421 fscp->fs_flags |= CFS_FS_DIRTYINFO; 422 mutex_exit(&fscp->fs_fslock); 423 } 424 fscache_hold(fscp); 425 426 error = 0; 427 if (fscp->fs_fscdirvp) { 428 error = VOP_LOOKUP(fscp->fs_fscdirvp, CACHEFS_DLOG_FILE, 429 &tmpdirvp, NULL, 0, NULL, kcred); 430 431 /* 432 * If a log file exists and the cache is being mounted without 433 * the snr (aka disconnectable) option, return an error. 434 */ 435 if ((error == 0) && 436 !(cfs_options->opt_flags & CFS_DISCONNECTABLE)) { 437 mutex_exit(&cachep->c_fslistlock); 438 cmn_err(CE_WARN, "cachefs: log exists and " 439 "disconnectable option not specified\n"); 440 error = EINVAL; 441 goto out; 442 } 443 } 444 445 /* 446 * Acquire the name of the mount point 447 */ 448 if (fscp->fs_mntpt == NULL) { 449 /* 450 * the string length returned by copystr includes the 451 * terminating NULL character, unless a NULL string is 452 * passed in, then the string length is unchanged. 453 */ 454 strl = 0; 455 tmpstr[0] = '\0'; 456 (void) copyinstr(uap->dir, tmpstr, MAXPATHLEN, &strl); 457 if (strl > 1) { 458 fscp->fs_mntpt = kmem_alloc(strl, KM_SLEEP); 459 (void) strncpy(fscp->fs_mntpt, tmpstr, strl); 460 } 461 /* 462 * else fscp->fs_mntpt is unchanged(still NULL) try again 463 * next time 464 */ 465 } 466 467 /* 468 * Acquire the name of the server 469 */ 470 if (fscp->fs_hostname == NULL) { 471 strl = 0; 472 tmpstr[0] = '\0'; 473 /*LINTED 32-bit pointer casting okay*/ 474 (void) copyinstr((char *)STRUCT_FGETP(map, cfs_hostname), 475 tmpstr, MAXPATHLEN, &strl); 476 if (strl > 1) { 477 fscp->fs_hostname = kmem_alloc(strl, KM_SLEEP); 478 (void) strncpy(fscp->fs_hostname, tmpstr, strl); 479 } 480 /* 481 * else fscp->fs_hostname remains unchanged (is still NULL) 482 */ 483 } 484 485 /* 486 * Acquire name of the back filesystem 487 */ 488 if (fscp->fs_backfsname == NULL) { 489 strl = 0; 490 tmpstr[0] = '\0'; 491 /*LINTED 32-bit pointer casting okay*/ 492 (void) copyinstr((char *)STRUCT_FGETP(map, cfs_backfsname), 493 tmpstr, MAXPATHLEN, &strl); 494 if (strl > 1) { 495 fscp->fs_backfsname = kmem_alloc(strl, KM_SLEEP); 496 (void) strncpy(fscp->fs_backfsname, tmpstr, strl); 497 } 498 /* 499 * else fscp->fs_backfsname remains unchanged (is still NULL) 500 */ 501 } 502 503 backfileno = fscp->fs_info.fi_root; 504 mutex_exit(&cachep->c_fslistlock); 505 506 /* see if fscache object is already mounted, it not, make it so */ 507 error = fscache_mounted(fscp, vfsp, backvfsp); 508 if (error) { 509 /* fs cache was already mounted */ 510 error = EBUSY; 511 goto out; 512 } 513 514 cachefs_kstat_mount(fscp, uap->dir, backmntpt, cachedir, cacheid); 515 516 /* set nfs style time out parameters */ 517 fscache_acset(fscp, STRUCT_FGET(map, cfs_acregmin), 518 STRUCT_FGET(map, cfs_acregmax), 519 STRUCT_FGET(map, cfs_acdirmin), STRUCT_FGET(map, cfs_acdirmax)); 520 521 vfsp->vfs_dev = cachefs_dev; 522 vfsp->vfs_data = (caddr_t)fscp; 523 vfs_make_fsid(&vfsp->vfs_fsid, cachefs_dev, cachefsfstyp); 524 vfsp->vfs_fstype = cachefsfstyp; 525 if (backvfsp) 526 vfsp->vfs_bsize = backvfsp->vfs_bsize; 527 else 528 vfsp->vfs_bsize = MAXBSIZE; /* XXX */ 529 530 /* make a cnode for the root of the file system */ 531 cid.cid_flags = 0; 532 cid.cid_fileno = backfileno; 533 error = cachefs_cnode_make(&cid, fscp, (valid_fid ? cookiep : NULL), 534 attrp, backrootvp, cr, CN_ROOT, &cp); 535 536 if (error) { 537 cmn_err(CE_WARN, "cachefs_mount: can't create root cnode\n"); 538 goto out; 539 } 540 541 /* stick the root cnode in the fscache object */ 542 mutex_enter(&fscp->fs_fslock); 543 fscp->fs_rootvp = CTOV(cp); 544 fscp->fs_rootvp->v_flag |= VROOT; 545 fscp->fs_rootvp->v_type |= cp->c_attr.va_type; 546 ASSERT(fscp->fs_rootvp->v_type == VDIR); 547 548 /* 549 * Get the maxfilesize bits of the back file system. 550 */ 551 552 error = VOP_PATHCONF(backrootvp, _PC_FILESIZEBITS, &maxfilesizebits, 553 kcred); 554 555 if (error) { 556 cmn_err(CE_WARN, 557 "cachefs_mount: Can't get the FILESIZEBITS of the back root vnode \n"); 558 goto out; 559 } 560 561 fscp->fs_offmax = (1LL << (maxfilesizebits - 1)) - 1; 562 mutex_exit(&fscp->fs_fslock); 563 564 /* remove the unmount file if it is there */ 565 (void) VOP_REMOVE(fscp->fs_fscdirvp, CACHEFS_UNMNT_FILE, kcred); 566 567 /* wake up the cache worker if ANY packed pending work */ 568 mutex_enter(&cachep->c_contentslock); 569 if (cachep->c_flags & CACHE_PACKED_PENDING) 570 cv_signal(&cachep->c_cwcv); 571 mutex_exit(&cachep->c_contentslock); 572 573 /* 574 * Warn that caching is disabled with NFSv4 first time around. 575 */ 576 if (!cachefs_nfsv4_warnmsg && CFS_ISFS_BACKFS_NFSV4(fscp)) { 577 cmn_err(CE_WARN, 578 "Cachefs has detected a mount with NFSv4: caching will" 579 " be disabled for this and other NFSv4 mounts\n"); 580 cachefs_nfsv4_warnmsg = TRUE; 581 } 582 583 out: 584 /* 585 * make a log entry, if appropriate 586 */ 587 588 if ((cachep != NULL) && 589 CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MOUNT)) 590 cachefs_log_mount(cachep, error, vfsp, fscp, 591 uap->dir, UIO_USERSPACE, 592 (STRUCT_BUF(map) != NULL) ? cacheid : NULL); 593 594 /* 595 * Cleanup our mess 596 */ 597 if (cookiep != NULL) 598 cachefs_kmem_free(cookiep, sizeof (struct fid)); 599 if (cachedirvp != NULL) 600 VN_RELE(cachedirvp); 601 if (backrootvp != NULL) 602 VN_RELE(backrootvp); 603 if (fscp) 604 fscache_rele(fscp); 605 if (attrp) 606 cachefs_kmem_free(attrp, sizeof (struct vattr)); 607 608 if (error) { 609 if (cachep) { 610 int xx; 611 612 /* lock the cachep's fslist */ 613 mutex_enter(&cachep->c_fslistlock); 614 615 /* 616 * gc isn't necessary for list_mounted(), but 617 * we want to do it anyway. 618 */ 619 620 fscache_list_gc(cachep); 621 xx = fscache_list_mounted(cachep); 622 623 mutex_exit(&cachep->c_fslistlock); 624 625 /* if no more references to this cachep, punt it. */ 626 if (xx == 0) 627 cachefs_delete_cachep(cachep); 628 mutex_exit(&cachefs_cachelock); 629 } 630 } else { 631 mutex_exit(&cachefs_cachelock); 632 } 633 634 #ifdef CFSDEBUG 635 CFS_DEBUG(CFSDEBUG_VFSOP) 636 printf("cachefs_mount: EXIT\n"); 637 #endif 638 return (error); 639 } 640 641 void 642 cachefs_kstat_mount(struct fscache *fscp, 643 char *umountpoint, char *ubackfs, char *ucachedir, char *cacheid) 644 { 645 cachefscache_t *cachep = fscp->fs_cache; 646 cachefs_kstat_key_t *key; 647 char *mountpoint = NULL, *backfs = NULL, *cachedir = NULL; 648 size_t len; 649 kstat_t *ksp; 650 int i, rc; 651 652 mountpoint = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 653 if (copyinstr(umountpoint, mountpoint, MAXPATHLEN, &len) != 0) 654 goto out; 655 656 cachedir = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 657 if (copyinstr(ucachedir, cachedir, MAXPATHLEN, &len) != 0) 658 goto out; 659 660 backfs = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 661 if (backfs) { 662 if (copyinstr(ubackfs, backfs, MAXPATHLEN, &len) != 0) 663 goto out; 664 } else { 665 (void) strcpy(backfs, "no back file system"); 666 } 667 668 ASSERT(strlen(mountpoint) < MAXPATHLEN); 669 ASSERT(strlen(backfs) < MAXPATHLEN); 670 ASSERT(strlen(cachedir) < MAXPATHLEN); 671 672 /* protect cachefs_kstat_key */ 673 mutex_enter(&cachefs_kstat_key_lock); 674 /* 675 * XXXX If already there, why not go straight to it? 676 * We know that fscp->fs_kstat_id == i + 1 677 */ 678 i = fscp->fs_kstat_id - 1; 679 if ((i >= 0) && (i < cachefs_kstat_key_n)) 680 rc = 1; 681 else 682 rc = i = 0; 683 for (; i < cachefs_kstat_key_n; i++) { 684 key = cachefs_kstat_key + i; 685 if (strcmp((char *)(uintptr_t)key->ks_mountpoint, 686 mountpoint) == 0 && 687 strcmp((char *)(uintptr_t)key->ks_cachedir, 688 cachedir) == 0 && 689 strcmp((char *)(uintptr_t)key->ks_cacheid, cacheid) == 0) 690 break; 691 if (rc) { /* direct key did not work - check all */ 692 i = -1; /* will increment to zero in loop */ 693 rc = 0; 694 } 695 } 696 697 if (i >= cachefs_kstat_key_n) { 698 key = cachefs_kmem_alloc((cachefs_kstat_key_n + 1) * 699 sizeof (cachefs_kstat_key_t), KM_SLEEP); 700 if (cachefs_kstat_key != NULL) { 701 bcopy(cachefs_kstat_key, key, 702 cachefs_kstat_key_n * sizeof (*key)); 703 cachefs_kmem_free(cachefs_kstat_key, 704 cachefs_kstat_key_n * sizeof (*key)); 705 } 706 cachefs_kstat_key = key; 707 key = cachefs_kstat_key + cachefs_kstat_key_n; 708 ++cachefs_kstat_key_n; 709 rc = key->ks_id = cachefs_kstat_key_n; /* offset + 1 */ 710 711 key->ks_mountpoint = (uint64_t)(uintptr_t) 712 cachefs_strdup(mountpoint); 713 key->ks_backfs = (uint64_t)(uintptr_t)cachefs_strdup(backfs); 714 key->ks_cachedir = (uint64_t)(uintptr_t) 715 cachefs_strdup(cachedir); 716 key->ks_cacheid = (uint64_t)(uintptr_t)cachefs_strdup(cacheid); 717 } else 718 rc = key->ks_id; 719 720 mutex_enter(&fscp->fs_fslock); /* protect fscp */ 721 722 fscp->fs_kstat_id = rc; 723 724 mutex_exit(&fscp->fs_fslock); /* finished with fscp */ 725 /* finished cachefs_kstat_key */ 726 mutex_exit(&cachefs_kstat_key_lock); 727 728 key->ks_vfsp = (uint64_t)(uintptr_t)fscp->fs_cfsvfsp; 729 key->ks_mounted = 1; 730 731 /* 732 * we must not be holding any mutex that is a ks_lock field 733 * for one of the kstats when we invoke kstat_create, 734 * kstat_install, and friends. 735 */ 736 ASSERT(MUTEX_NOT_HELD(&cachefs_kstat_key_lock)); 737 /* really should be EVERY cachep's c_log_mutex */ 738 ASSERT(MUTEX_NOT_HELD(&cachep->c_log_mutex)); 739 740 /* cachefs.#.log */ 741 ksp = kstat_create("cachefs", fscp->fs_kstat_id, "log", 742 "misc", KSTAT_TYPE_RAW, 1, 743 KSTAT_FLAG_WRITABLE | KSTAT_FLAG_VIRTUAL); 744 if (ksp != NULL) { 745 ksp->ks_data = cachep->c_log_ctl; 746 ksp->ks_data_size = sizeof (cachefs_log_control_t); 747 ksp->ks_lock = &cachep->c_log_mutex; 748 ksp->ks_snapshot = cachefs_log_kstat_snapshot; 749 kstat_install(ksp); 750 } 751 /* cachefs.#.stats */ 752 ksp = kstat_create("cachefs", fscp->fs_kstat_id, "stats", 753 "misc", KSTAT_TYPE_RAW, 1, 754 KSTAT_FLAG_WRITABLE | KSTAT_FLAG_VIRTUAL); 755 if (ksp != NULL) { 756 ksp->ks_data = fscp; 757 ksp->ks_data_size = sizeof (cachefs_stats_t); 758 ksp->ks_snapshot = cachefs_stats_kstat_snapshot; 759 kstat_install(ksp); 760 } 761 762 out: 763 if (mountpoint != NULL) 764 cachefs_kmem_free(mountpoint, MAXPATHLEN); 765 if (backfs != NULL) 766 cachefs_kmem_free(backfs, MAXPATHLEN); 767 if (cachedir != NULL) 768 cachefs_kmem_free(cachedir, MAXPATHLEN); 769 } 770 771 void 772 cachefs_kstat_umount(int ksid) 773 { 774 cachefs_kstat_key_t *k = cachefs_kstat_key + (ksid - 1); 775 776 ASSERT(k->ks_id == ksid); 777 778 k->ks_mounted = 0; 779 780 kstat_delete_byname("cachefs", ksid, "stats"); 781 kstat_delete_byname("cachefs", ksid, "log"); 782 } 783 784 int 785 cachefs_kstat_key_update(kstat_t *ksp, int rw) 786 { 787 cachefs_kstat_key_t *key = *((cachefs_kstat_key_t **)ksp->ks_data); 788 cachefs_kstat_key_t *k; 789 int i; 790 791 if (rw == KSTAT_WRITE) 792 return (EIO); 793 if (key == NULL) 794 return (EIO); 795 796 ksp->ks_data_size = cachefs_kstat_key_n * sizeof (*key); 797 for (i = 0; i < cachefs_kstat_key_n; i++) { 798 k = key + i; 799 800 ksp->ks_data_size += 801 strlen((char *)(uintptr_t)k->ks_mountpoint) + 1; 802 ksp->ks_data_size += 803 strlen((char *)(uintptr_t)k->ks_backfs) + 1; 804 ksp->ks_data_size += 805 strlen((char *)(uintptr_t)k->ks_cachedir) + 1; 806 ksp->ks_data_size += 807 strlen((char *)(uintptr_t)k->ks_cacheid) + 1; 808 } 809 810 ksp->ks_ndata = cachefs_kstat_key_n; 811 812 return (0); 813 } 814 815 int 816 cachefs_kstat_key_snapshot(kstat_t *ksp, void *buf, int rw) 817 { 818 cachefs_kstat_key_t *key = *((cachefs_kstat_key_t **)ksp->ks_data); 819 cachefs_kstat_key_t *k; 820 caddr_t s; 821 int i; 822 823 if (rw == KSTAT_WRITE) 824 return (EIO); 825 826 if (key == NULL) 827 return (0); /* paranoid */ 828 829 bcopy(key, buf, cachefs_kstat_key_n * sizeof (*key)); 830 key = buf; 831 s = (caddr_t)(key + cachefs_kstat_key_n); 832 833 for (i = 0; i < cachefs_kstat_key_n; i++) { 834 k = key + i; 835 836 (void) strcpy(s, (char *)(uintptr_t)k->ks_mountpoint); 837 k->ks_mountpoint = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 838 s += strlen(s) + 1; 839 (void) strcpy(s, (char *)(uintptr_t)k->ks_backfs); 840 k->ks_backfs = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 841 s += strlen(s) + 1; 842 (void) strcpy(s, (char *)(uintptr_t)k->ks_cachedir); 843 k->ks_cachedir = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 844 s += strlen(s) + 1; 845 (void) strcpy(s, (char *)(uintptr_t)k->ks_cacheid); 846 k->ks_cacheid = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 847 s += strlen(s) + 1; 848 } 849 850 return (0); 851 } 852 853 extern void cachefs_inactivate(); 854 855 static int 856 cachefs_unmount(vfs_t *vfsp, int flag, cred_t *cr) 857 { 858 fscache_t *fscp = VFS_TO_FSCACHE(vfsp); 859 struct cachefscache *cachep = fscp->fs_cache; 860 int error; 861 int xx; 862 vnode_t *nmvp; 863 struct vattr attr; 864 865 #ifdef CFSDEBUG 866 CFS_DEBUG(CFSDEBUG_VFSOP) 867 printf("cachefs_unmount: ENTER fscp %p\n", fscp); 868 #endif 869 870 if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0) 871 goto out; 872 873 /* 874 * forced unmount is not supported by this file system 875 * and thus, ENOTSUP, is being returned. 876 */ 877 if (flag & MS_FORCE) { 878 error = ENOTSUP; 879 goto out; 880 } 881 /* if a log file exists don't allow the unmount */ 882 if (fscp->fs_dlogfile) { 883 error = EBUSY; 884 goto out; 885 } 886 887 /* 888 * wait for the cache-wide async queue to drain. Someone 889 * here may be trying to sync our fscache... 890 */ 891 while (cachefs_async_halt(&fscp->fs_cache->c_workq, 0) == EBUSY) { 892 #ifdef CFSDEBUG 893 CFS_DEBUG(CFSDEBUG_VFSOP) 894 printf("unmount: waiting for cache async queue...\n"); 895 #endif 896 } 897 898 error = cachefs_async_halt(&fscp->fs_workq, 1); 899 if (error) { 900 #ifdef CFSDEBUG 901 CFS_DEBUG(CFSDEBUG_VFSOP) 902 printf("cachefs_unmount: " 903 "cachefs_async_halt error %d\n", error); 904 #endif 905 goto out; 906 } 907 908 /* 909 * No active cnodes on this cache && rootvp refcnt == 1 910 */ 911 mutex_enter(&fscp->fs_fslock); 912 xx = fscp->fs_cnodecnt - fscp->fs_idlecnt; 913 ASSERT(xx >= 1); 914 if (xx > 1 || fscp->fs_rootvp->v_count != 1) { 915 mutex_exit(&fscp->fs_fslock); 916 #ifdef CFSDEBUG 917 CFS_DEBUG(CFSDEBUG_VFSOP) 918 printf("cachefs_unmount: busy (cnodes active %d, idle " 919 "%d)\n", fscp->fs_cnodecnt, fscp->fs_idlecnt); 920 #endif 921 error = EBUSY; 922 goto out; 923 } 924 mutex_exit(&fscp->fs_fslock); 925 926 /* get rid of anything on the idle list */ 927 ASSERT(fscp->fs_idleclean == 0); 928 cachefs_cnode_idleclean(fscp, 1); 929 if (fscp->fs_cnodecnt > 1) { 930 #ifdef CFSDEBUG 931 CFS_DEBUG(CFSDEBUG_VFSOP) 932 printf("cachefs_unmount: busy (cnode count %d)\n", 933 fscp->fs_cnodecnt); 934 #endif 935 error = EBUSY; 936 goto out; 937 } 938 939 fscache_hold(fscp); 940 941 /* get rid of the root cnode */ 942 if (cachefs_cnode_inactive(fscp->fs_rootvp, cr) == EBUSY) { 943 fscache_rele(fscp); 944 #ifdef CFSDEBUG 945 CFS_DEBUG(CFSDEBUG_VFSOP) 946 printf("cachefs_unmount: busy (inactive failed)\n"); 947 #endif 948 error = EBUSY; 949 goto out; 950 } 951 952 /* create the file indicating not mounted */ 953 attr.va_mode = S_IFREG | 0666; 954 attr.va_uid = 0; 955 attr.va_gid = 0; 956 attr.va_type = VREG; 957 attr.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 958 if (fscp->fs_fscdirvp != NULL) 959 xx = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_UNMNT_FILE, &attr, 960 NONEXCL, 0600, &nmvp, kcred, 0); 961 else 962 xx = ENOENT; /* for unmounting when NOCACHE */ 963 if (xx == 0) { 964 VN_RELE(nmvp); 965 } else { 966 printf("could not create %s %d\n", CACHEFS_UNMNT_FILE, xx); 967 } 968 969 ASSERT(fscp->fs_cnodecnt == 0); 970 971 /* sync the file system just in case */ 972 fscache_sync(fscp); 973 974 /* lock out other unmounts and mount */ 975 mutex_enter(&cachefs_cachelock); 976 977 /* mark the file system as not mounted */ 978 mutex_enter(&fscp->fs_fslock); 979 fscp->fs_flags &= ~CFS_FS_MOUNTED; 980 fscp->fs_rootvp = NULL; 981 if (fscp->fs_kstat_id > 0) 982 cachefs_kstat_umount(fscp->fs_kstat_id); 983 fscp->fs_kstat_id = 0; 984 985 /* drop the inum translation table */ 986 if (fscp->fs_inum_size > 0) { 987 cachefs_kmem_free(fscp->fs_inum_trans, 988 fscp->fs_inum_size * sizeof (cachefs_inum_trans_t)); 989 fscp->fs_inum_size = 0; 990 fscp->fs_inum_trans = NULL; 991 fscp->fs_flags &= ~CFS_FS_HASHPRINT; 992 } 993 mutex_exit(&fscp->fs_fslock); 994 995 fscache_rele(fscp); 996 997 /* get rid of any unused fscache objects */ 998 mutex_enter(&cachep->c_fslistlock); 999 fscache_list_gc(cachep); 1000 mutex_exit(&cachep->c_fslistlock); 1001 1002 /* get the number of mounts on this cache */ 1003 mutex_enter(&cachep->c_fslistlock); 1004 xx = fscache_list_mounted(cachep); 1005 mutex_exit(&cachep->c_fslistlock); 1006 1007 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_UMOUNT)) 1008 cachefs_log_umount(cachep, 0, vfsp); 1009 1010 /* if no mounts left, deactivate the cache */ 1011 if (xx == 0) 1012 cachefs_delete_cachep(cachep); 1013 1014 mutex_exit(&cachefs_cachelock); 1015 1016 out: 1017 if (error) { 1018 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_UMOUNT)) 1019 cachefs_log_umount(cachep, error, vfsp); 1020 } 1021 #ifdef CFSDEBUG 1022 CFS_DEBUG(CFSDEBUG_VFSOP) 1023 printf("cachefs_unmount: EXIT\n"); 1024 #endif 1025 return (error); 1026 } 1027 1028 /* 1029 * remove the cache from the list of caches 1030 */ 1031 1032 static void 1033 cachefs_delete_cachep(cachefscache_t *cachep) 1034 { 1035 struct cachefscache **cachepp; 1036 int found = 0; 1037 1038 ASSERT(MUTEX_HELD(&cachefs_cachelock)); 1039 1040 for (cachepp = &cachefs_cachelist; 1041 *cachepp != NULL; 1042 cachepp = &(*cachepp)->c_next) { 1043 if (*cachepp == cachep) { 1044 *cachepp = cachep->c_next; 1045 found++; 1046 break; 1047 } 1048 } 1049 ASSERT(found); 1050 1051 /* shut down the cache */ 1052 cachefs_cache_destroy(cachep); 1053 } 1054 1055 static int 1056 cachefs_root(vfs_t *vfsp, vnode_t **vpp) 1057 { 1058 /*LINTED alignment okay*/ 1059 struct fscache *fscp = (struct fscache *)vfsp->vfs_data; 1060 1061 ASSERT(fscp != NULL); 1062 ASSERT(fscp->fs_rootvp != NULL); 1063 1064 if (getzoneid() != GLOBAL_ZONEID) 1065 return (EPERM); 1066 *vpp = fscp->fs_rootvp; 1067 VN_HOLD(*vpp); 1068 return (0); 1069 } 1070 1071 /* 1072 * Get file system statistics. 1073 */ 1074 static int 1075 cachefs_statvfs(register vfs_t *vfsp, struct statvfs64 *sbp) 1076 { 1077 struct fscache *fscp = VFS_TO_FSCACHE(vfsp); 1078 struct cache_label *lp = &fscp->fs_cache->c_label; 1079 struct cache_usage *up = &fscp->fs_cache->c_usage; 1080 int error; 1081 1082 if (getzoneid() != GLOBAL_ZONEID) 1083 return (EPERM); 1084 error = cachefs_cd_access(fscp, 0, 0); 1085 if (error) 1086 return (error); 1087 1088 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) { 1089 /* 1090 * When connected return backfs stats 1091 */ 1092 error = VFS_STATVFS(fscp->fs_backvfsp, sbp); 1093 } else { 1094 /* 1095 * Otherwise, just return the frontfs stats 1096 */ 1097 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1098 error = VFS_STATVFS(fscp->fs_fscdirvp->v_vfsp, sbp); 1099 if (!error) { 1100 dev32_t d32; 1101 1102 sbp->f_frsize = MAXBSIZE; 1103 sbp->f_blocks = lp->cl_maxblks; 1104 sbp->f_bfree = sbp->f_bavail = 1105 lp->cl_maxblks - up->cu_blksused; 1106 sbp->f_files = lp->cl_maxinodes; 1107 sbp->f_ffree = sbp->f_favail = 1108 lp->cl_maxinodes - up->cu_filesused; 1109 (void) cmpldev(&d32, vfsp->vfs_dev); 1110 sbp->f_fsid = d32; 1111 } 1112 } 1113 cachefs_cd_release(fscp); 1114 if (error) 1115 return (error); 1116 1117 /* 1118 * Make sure fstype is CFS. 1119 */ 1120 (void) strcpy(sbp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 1121 bzero(sbp->f_fstr, sizeof (sbp->f_fstr)); 1122 1123 return (0); 1124 } 1125 1126 /* 1127 * queue a request to sync the given fscache 1128 */ 1129 static void 1130 queue_sync(struct cachefscache *cachep, cred_t *cr) 1131 { 1132 struct cachefs_req *rp; 1133 1134 rp = kmem_cache_alloc(cachefs_req_cache, KM_SLEEP); 1135 rp->cfs_cmd = CFS_CACHE_SYNC; 1136 rp->cfs_cr = cr; 1137 rp->cfs_req_u.cu_fs_sync.cf_cachep = cachep; 1138 crhold(rp->cfs_cr); 1139 cachefs_addqueue(rp, &cachep->c_workq); 1140 } 1141 1142 /*ARGSUSED*/ 1143 static int 1144 cachefs_sync(vfs_t *vfsp, short flag, cred_t *cr) 1145 { 1146 struct fscache *fscp; 1147 struct cachefscache *cachep; 1148 1149 if (getzoneid() != GLOBAL_ZONEID) 1150 return (EPERM); 1151 if (!(flag & SYNC_ATTR)) { 1152 /* 1153 * queue an async request to do the sync. 1154 * We always sync an entire cache (as opposed to an 1155 * individual fscache) so that we have an opportunity 1156 * to set the clean flag. 1157 */ 1158 if (vfsp) { 1159 /*LINTED alignment okay*/ 1160 fscp = (struct fscache *)vfsp->vfs_data; 1161 queue_sync(fscp->fs_cache, cr); 1162 } else { 1163 mutex_enter(&cachefs_cachelock); 1164 for (cachep = cachefs_cachelist; cachep != NULL; 1165 cachep = cachep->c_next) { 1166 queue_sync(cachep, cr); 1167 } 1168 mutex_exit(&cachefs_cachelock); 1169 } 1170 } 1171 return (0); 1172 } 1173 1174 static int 1175 cachefs_remount(struct vfs *vfsp, struct mounta *uap) 1176 { 1177 fscache_t *fscp = VFS_TO_FSCACHE(vfsp); 1178 cachefscache_t *cachep = fscp->fs_cache; 1179 int error = 0; 1180 STRUCT_DECL(cachefs_mountargs, map); 1181 struct cachefsoptions *cfs_options; 1182 char *backfs, *cacheid, *cachedir; 1183 struct vnode *cachedirvp = NULL; 1184 ino64_t fsid; 1185 vnode_t *backrootvp = NULL; 1186 struct vnode *tmpdirvp = NULL; 1187 1188 STRUCT_INIT(map, get_udatamodel()); 1189 error = copyin(uap->dataptr, STRUCT_BUF(map), 1190 SIZEOF_STRUCT(cachefs_mountargs, DATAMODEL_NATIVE)); 1191 if (error) 1192 goto out; 1193 1194 /* 1195 * get cache directory vp 1196 */ 1197 cachedir = (char *)STRUCT_FGETP(map, cfs_cachedir); 1198 error = lookupname(cachedir, UIO_USERSPACE, FOLLOW, 1199 NULLVPP, &cachedirvp); 1200 if (error) 1201 goto out; 1202 if (cachedirvp->v_type != VDIR) { 1203 error = EINVAL; 1204 goto out; 1205 } 1206 1207 error = 0; 1208 if (cachedirvp) { 1209 error = VOP_LOOKUP(cachedirvp, CACHEFS_DLOG_FILE, 1210 &tmpdirvp, NULL, 0, NULL, kcred); 1211 } 1212 cfs_options = (struct cachefsoptions *)STRUCT_FADDR(map, cfs_options); 1213 cacheid = (char *)STRUCT_FGETP(map, cfs_cacheid); 1214 /* XXX not quite right */ 1215 #if 0 1216 /* 1217 * If a log file exists and the cache is being mounted without 1218 * the snr (aka disconnectable) option, return an error. 1219 */ 1220 if ((error == 0) && 1221 !(cfs_options->opt_flags & CFS_DISCONNECTABLE)) { 1222 cmn_err(CE_WARN, 1223 "cachefs_mount: log exists and disconnectable" 1224 "option not specified\n"); 1225 error = EINVAL; 1226 goto out; 1227 } 1228 #endif 1229 error = 0; 1230 1231 /* 1232 * If the user is using NFSv4 and there are other options 1233 * specified, make sure we ignore the other options. 1234 */ 1235 if (CFS_ISFS_BACKFS_NFSV4(fscp)) { 1236 cfs_options->opt_flags = CFS_BACKFS_NFSV4; 1237 } 1238 1239 /* XXX need mount options "nocache" and "nofill" */ 1240 1241 /* if nocache is being turned off */ 1242 if (cachep->c_flags & CACHE_NOCACHE) { 1243 error = cachefs_cache_activate_ro(cachep, cachedirvp); 1244 if (error) 1245 goto out; 1246 cachefs_cache_activate_rw(cachep); 1247 1248 /* get the fsid for the fscache */ 1249 error = fscache_name_to_fsid(cachep, cacheid, &fsid); 1250 if (error) 1251 fsid = 0; 1252 1253 /* activate the fscache */ 1254 mutex_enter(&cachep->c_fslistlock); 1255 error = fscache_enable(fscp, fsid, cacheid, 1256 cfs_options, fscp->fs_info.fi_root); 1257 mutex_exit(&cachep->c_fslistlock); 1258 if (error) { 1259 cmn_err(CE_WARN, "cachefs: cannot remount %s\n", 1260 cacheid); 1261 goto out; 1262 } 1263 1264 /* enable the cache */ 1265 cachefs_enable_caching(fscp); 1266 fscache_activate_rw(fscp); 1267 } 1268 1269 /* else if nofill is being turn off */ 1270 else if (cachep->c_flags & CACHE_NOFILL) { 1271 ASSERT(cachep->c_flags & CACHE_NOFILL); 1272 cachefs_cache_activate_rw(cachep); 1273 1274 /* enable the cache */ 1275 cachefs_enable_caching(fscp); 1276 fscache_activate_rw(fscp); 1277 } 1278 1279 fscache_acset(fscp, STRUCT_FGET(map, cfs_acregmin), 1280 STRUCT_FGET(map, cfs_acregmax), 1281 STRUCT_FGET(map, cfs_acdirmin), STRUCT_FGET(map, cfs_acdirmax)); 1282 1283 /* if the backfs is mounted now or we have a new backfs */ 1284 backfs = (char *)STRUCT_FGETP(map, cfs_backfs); 1285 if (backfs && (cfs_options->opt_flags & CFS_SLIDE)) { 1286 /* get the back file system root vp */ 1287 error = lookupname(backfs, UIO_USERSPACE, FOLLOW, 1288 NULLVPP, &backrootvp); 1289 if (error) 1290 goto out; 1291 1292 /* 1293 * Make sure the thing we just looked up is a directory 1294 * and a root of a file system 1295 */ 1296 if (backrootvp->v_type != VDIR || 1297 !(backrootvp->v_flag & VROOT)) { 1298 cmn_err(CE_WARN, 1299 "cachefs_mount: backpath not a directory\n"); 1300 error = EINVAL; 1301 goto out; 1302 } 1303 1304 /* 1305 * XXX 1306 * Kind of dangerous to just set this but we do 1307 * not have locks around usage of fs_backvfsp. 1308 * Hope for the best for now. 1309 * Probably should also spin through vnodes and fix them up. 1310 * Krishna - fixed c_backvp to reflect the change. 1311 */ 1312 fscp->fs_backvfsp = backrootvp->v_vfsp; 1313 ((cnode_t *)(fscp->fs_rootvp->v_data))->c_backvp = backrootvp; 1314 1315 /* 1316 * Now the root cnode structure is an owner of 1317 * the opened back root vnode structure; we must 1318 * clear the pointer to back root vnode here as 1319 * we don't need it since now, and the root cnode 1320 * structure will control the vnode 1321 */ 1322 backrootvp = (vnode_t *)NULL; 1323 } 1324 1325 if (fscp->fs_kstat_id > 0) 1326 cachefs_kstat_umount(fscp->fs_kstat_id); 1327 fscp->fs_kstat_id = 0; 1328 cachefs_kstat_mount(fscp, uap->dir, backfs, cachedir, cacheid); 1329 1330 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MOUNT)) 1331 cachefs_log_mount(cachep, error, vfsp, fscp, 1332 uap->dir, UIO_USERSPACE, 1333 (STRUCT_BUF(map) != NULL) ? cacheid : NULL); 1334 1335 out: 1336 if (cachedirvp) 1337 VN_RELE(cachedirvp); 1338 if (backrootvp) 1339 VN_RELE(backrootvp); 1340 return (error); 1341 } 1342