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 compatible */ 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, NULL, NULL, NULL); 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, NULL); 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, NULL, 566 0); 567 568 /* wake up the cache worker if ANY packed pending work */ 569 mutex_enter(&cachep->c_contentslock); 570 if (cachep->c_flags & CACHE_PACKED_PENDING) 571 cv_signal(&cachep->c_cwcv); 572 mutex_exit(&cachep->c_contentslock); 573 574 /* 575 * Warn that caching is disabled with NFSv4 first time around. 576 */ 577 if (!cachefs_nfsv4_warnmsg && CFS_ISFS_BACKFS_NFSV4(fscp)) { 578 cmn_err(CE_WARN, 579 "Cachefs has detected a mount with NFSv4: caching will" 580 " be disabled for this and other NFSv4 mounts\n"); 581 cachefs_nfsv4_warnmsg = TRUE; 582 } 583 584 out: 585 /* 586 * make a log entry, if appropriate 587 */ 588 589 if ((cachep != NULL) && 590 CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MOUNT)) 591 cachefs_log_mount(cachep, error, vfsp, fscp, 592 uap->dir, UIO_USERSPACE, 593 (STRUCT_BUF(map) != NULL) ? cacheid : NULL); 594 595 /* 596 * Cleanup our mess 597 */ 598 if (cookiep != NULL) 599 cachefs_kmem_free(cookiep, sizeof (struct fid)); 600 if (cachedirvp != NULL) 601 VN_RELE(cachedirvp); 602 if (backrootvp != NULL) 603 VN_RELE(backrootvp); 604 if (fscp) 605 fscache_rele(fscp); 606 if (attrp) 607 cachefs_kmem_free(attrp, sizeof (struct vattr)); 608 609 if (error) { 610 if (cachep) { 611 int xx; 612 613 /* lock the cachep's fslist */ 614 mutex_enter(&cachep->c_fslistlock); 615 616 /* 617 * gc isn't necessary for list_mounted(), but 618 * we want to do it anyway. 619 */ 620 621 fscache_list_gc(cachep); 622 xx = fscache_list_mounted(cachep); 623 624 mutex_exit(&cachep->c_fslistlock); 625 626 /* if no more references to this cachep, punt it. */ 627 if (xx == 0) 628 cachefs_delete_cachep(cachep); 629 mutex_exit(&cachefs_cachelock); 630 } 631 } else { 632 mutex_exit(&cachefs_cachelock); 633 } 634 635 #ifdef CFSDEBUG 636 CFS_DEBUG(CFSDEBUG_VFSOP) 637 printf("cachefs_mount: EXIT\n"); 638 #endif 639 return (error); 640 } 641 642 void 643 cachefs_kstat_mount(struct fscache *fscp, 644 char *umountpoint, char *ubackfs, char *ucachedir, char *cacheid) 645 { 646 cachefscache_t *cachep = fscp->fs_cache; 647 cachefs_kstat_key_t *key; 648 char *mountpoint = NULL, *backfs = NULL, *cachedir = NULL; 649 size_t len; 650 kstat_t *ksp; 651 int i, rc; 652 653 mountpoint = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 654 if (copyinstr(umountpoint, mountpoint, MAXPATHLEN, &len) != 0) 655 goto out; 656 657 cachedir = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 658 if (copyinstr(ucachedir, cachedir, MAXPATHLEN, &len) != 0) 659 goto out; 660 661 backfs = cachefs_kmem_alloc(MAXPATHLEN, KM_SLEEP); 662 if (backfs) { 663 if (copyinstr(ubackfs, backfs, MAXPATHLEN, &len) != 0) 664 goto out; 665 } else { 666 (void) strcpy(backfs, "no back file system"); 667 } 668 669 ASSERT(strlen(mountpoint) < MAXPATHLEN); 670 ASSERT(strlen(backfs) < MAXPATHLEN); 671 ASSERT(strlen(cachedir) < MAXPATHLEN); 672 673 /* protect cachefs_kstat_key */ 674 mutex_enter(&cachefs_kstat_key_lock); 675 /* 676 * XXXX If already there, why not go straight to it? 677 * We know that fscp->fs_kstat_id == i + 1 678 */ 679 i = fscp->fs_kstat_id - 1; 680 if ((i >= 0) && (i < cachefs_kstat_key_n)) 681 rc = 1; 682 else 683 rc = i = 0; 684 for (; i < cachefs_kstat_key_n; i++) { 685 key = cachefs_kstat_key + i; 686 if (strcmp((char *)(uintptr_t)key->ks_mountpoint, 687 mountpoint) == 0 && 688 strcmp((char *)(uintptr_t)key->ks_cachedir, 689 cachedir) == 0 && 690 strcmp((char *)(uintptr_t)key->ks_cacheid, cacheid) == 0) 691 break; 692 if (rc) { /* direct key did not work - check all */ 693 i = -1; /* will increment to zero in loop */ 694 rc = 0; 695 } 696 } 697 698 if (i >= cachefs_kstat_key_n) { 699 key = cachefs_kmem_alloc((cachefs_kstat_key_n + 1) * 700 sizeof (cachefs_kstat_key_t), KM_SLEEP); 701 if (cachefs_kstat_key != NULL) { 702 bcopy(cachefs_kstat_key, key, 703 cachefs_kstat_key_n * sizeof (*key)); 704 cachefs_kmem_free(cachefs_kstat_key, 705 cachefs_kstat_key_n * sizeof (*key)); 706 } 707 cachefs_kstat_key = key; 708 key = cachefs_kstat_key + cachefs_kstat_key_n; 709 ++cachefs_kstat_key_n; 710 rc = key->ks_id = cachefs_kstat_key_n; /* offset + 1 */ 711 712 key->ks_mountpoint = (uint64_t)(uintptr_t) 713 cachefs_strdup(mountpoint); 714 key->ks_backfs = (uint64_t)(uintptr_t)cachefs_strdup(backfs); 715 key->ks_cachedir = (uint64_t)(uintptr_t) 716 cachefs_strdup(cachedir); 717 key->ks_cacheid = (uint64_t)(uintptr_t)cachefs_strdup(cacheid); 718 } else 719 rc = key->ks_id; 720 721 mutex_enter(&fscp->fs_fslock); /* protect fscp */ 722 723 fscp->fs_kstat_id = rc; 724 725 mutex_exit(&fscp->fs_fslock); /* finished with fscp */ 726 /* finished cachefs_kstat_key */ 727 mutex_exit(&cachefs_kstat_key_lock); 728 729 key->ks_vfsp = (uint64_t)(uintptr_t)fscp->fs_cfsvfsp; 730 key->ks_mounted = 1; 731 732 /* 733 * we must not be holding any mutex that is a ks_lock field 734 * for one of the kstats when we invoke kstat_create, 735 * kstat_install, and friends. 736 */ 737 ASSERT(MUTEX_NOT_HELD(&cachefs_kstat_key_lock)); 738 /* really should be EVERY cachep's c_log_mutex */ 739 ASSERT(MUTEX_NOT_HELD(&cachep->c_log_mutex)); 740 741 /* cachefs.#.log */ 742 ksp = kstat_create("cachefs", fscp->fs_kstat_id, "log", 743 "misc", KSTAT_TYPE_RAW, 1, 744 KSTAT_FLAG_WRITABLE | KSTAT_FLAG_VIRTUAL); 745 if (ksp != NULL) { 746 ksp->ks_data = cachep->c_log_ctl; 747 ksp->ks_data_size = sizeof (cachefs_log_control_t); 748 ksp->ks_lock = &cachep->c_log_mutex; 749 ksp->ks_snapshot = cachefs_log_kstat_snapshot; 750 kstat_install(ksp); 751 } 752 /* cachefs.#.stats */ 753 ksp = kstat_create("cachefs", fscp->fs_kstat_id, "stats", 754 "misc", KSTAT_TYPE_RAW, 1, 755 KSTAT_FLAG_WRITABLE | KSTAT_FLAG_VIRTUAL); 756 if (ksp != NULL) { 757 ksp->ks_data = fscp; 758 ksp->ks_data_size = sizeof (cachefs_stats_t); 759 ksp->ks_snapshot = cachefs_stats_kstat_snapshot; 760 kstat_install(ksp); 761 } 762 763 out: 764 if (mountpoint != NULL) 765 cachefs_kmem_free(mountpoint, MAXPATHLEN); 766 if (backfs != NULL) 767 cachefs_kmem_free(backfs, MAXPATHLEN); 768 if (cachedir != NULL) 769 cachefs_kmem_free(cachedir, MAXPATHLEN); 770 } 771 772 void 773 cachefs_kstat_umount(int ksid) 774 { 775 cachefs_kstat_key_t *k = cachefs_kstat_key + (ksid - 1); 776 777 ASSERT(k->ks_id == ksid); 778 779 k->ks_mounted = 0; 780 781 kstat_delete_byname("cachefs", ksid, "stats"); 782 kstat_delete_byname("cachefs", ksid, "log"); 783 } 784 785 int 786 cachefs_kstat_key_update(kstat_t *ksp, int rw) 787 { 788 cachefs_kstat_key_t *key = *((cachefs_kstat_key_t **)ksp->ks_data); 789 cachefs_kstat_key_t *k; 790 int i; 791 792 if (rw == KSTAT_WRITE) 793 return (EIO); 794 if (key == NULL) 795 return (EIO); 796 797 ksp->ks_data_size = cachefs_kstat_key_n * sizeof (*key); 798 for (i = 0; i < cachefs_kstat_key_n; i++) { 799 k = key + i; 800 801 ksp->ks_data_size += 802 strlen((char *)(uintptr_t)k->ks_mountpoint) + 1; 803 ksp->ks_data_size += 804 strlen((char *)(uintptr_t)k->ks_backfs) + 1; 805 ksp->ks_data_size += 806 strlen((char *)(uintptr_t)k->ks_cachedir) + 1; 807 ksp->ks_data_size += 808 strlen((char *)(uintptr_t)k->ks_cacheid) + 1; 809 } 810 811 ksp->ks_ndata = cachefs_kstat_key_n; 812 813 return (0); 814 } 815 816 int 817 cachefs_kstat_key_snapshot(kstat_t *ksp, void *buf, int rw) 818 { 819 cachefs_kstat_key_t *key = *((cachefs_kstat_key_t **)ksp->ks_data); 820 cachefs_kstat_key_t *k; 821 caddr_t s; 822 int i; 823 824 if (rw == KSTAT_WRITE) 825 return (EIO); 826 827 if (key == NULL) 828 return (0); /* paranoid */ 829 830 bcopy(key, buf, cachefs_kstat_key_n * sizeof (*key)); 831 key = buf; 832 s = (caddr_t)(key + cachefs_kstat_key_n); 833 834 for (i = 0; i < cachefs_kstat_key_n; i++) { 835 k = key + i; 836 837 (void) strcpy(s, (char *)(uintptr_t)k->ks_mountpoint); 838 k->ks_mountpoint = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 839 s += strlen(s) + 1; 840 (void) strcpy(s, (char *)(uintptr_t)k->ks_backfs); 841 k->ks_backfs = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 842 s += strlen(s) + 1; 843 (void) strcpy(s, (char *)(uintptr_t)k->ks_cachedir); 844 k->ks_cachedir = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 845 s += strlen(s) + 1; 846 (void) strcpy(s, (char *)(uintptr_t)k->ks_cacheid); 847 k->ks_cacheid = (uint64_t)(uintptr_t)(s - (uintptr_t)buf); 848 s += strlen(s) + 1; 849 } 850 851 return (0); 852 } 853 854 extern void cachefs_inactivate(); 855 856 static int 857 cachefs_unmount(vfs_t *vfsp, int flag, cred_t *cr) 858 { 859 fscache_t *fscp = VFS_TO_FSCACHE(vfsp); 860 struct cachefscache *cachep = fscp->fs_cache; 861 int error; 862 int xx; 863 vnode_t *nmvp; 864 struct vattr attr; 865 866 #ifdef CFSDEBUG 867 CFS_DEBUG(CFSDEBUG_VFSOP) 868 printf("cachefs_unmount: ENTER fscp %p\n", fscp); 869 #endif 870 871 if ((error = secpolicy_fs_unmount(cr, vfsp)) != 0) 872 goto out; 873 874 /* 875 * forced unmount is not supported by this file system 876 * and thus, ENOTSUP, is being returned. 877 */ 878 if (flag & MS_FORCE) { 879 error = ENOTSUP; 880 goto out; 881 } 882 /* if a log file exists don't allow the unmount */ 883 if (fscp->fs_dlogfile) { 884 error = EBUSY; 885 goto out; 886 } 887 888 /* 889 * wait for the cache-wide async queue to drain. Someone 890 * here may be trying to sync our fscache... 891 */ 892 while (cachefs_async_halt(&fscp->fs_cache->c_workq, 0) == EBUSY) { 893 #ifdef CFSDEBUG 894 CFS_DEBUG(CFSDEBUG_VFSOP) 895 printf("unmount: waiting for cache async queue...\n"); 896 #endif 897 } 898 899 error = cachefs_async_halt(&fscp->fs_workq, 1); 900 if (error) { 901 #ifdef CFSDEBUG 902 CFS_DEBUG(CFSDEBUG_VFSOP) 903 printf("cachefs_unmount: " 904 "cachefs_async_halt error %d\n", error); 905 #endif 906 goto out; 907 } 908 909 /* 910 * No active cnodes on this cache && rootvp refcnt == 1 911 */ 912 mutex_enter(&fscp->fs_fslock); 913 xx = fscp->fs_cnodecnt - fscp->fs_idlecnt; 914 ASSERT(xx >= 1); 915 if (xx > 1 || fscp->fs_rootvp->v_count != 1) { 916 mutex_exit(&fscp->fs_fslock); 917 #ifdef CFSDEBUG 918 CFS_DEBUG(CFSDEBUG_VFSOP) 919 printf("cachefs_unmount: busy (cnodes active %d, idle " 920 "%d)\n", fscp->fs_cnodecnt, fscp->fs_idlecnt); 921 #endif 922 error = EBUSY; 923 goto out; 924 } 925 mutex_exit(&fscp->fs_fslock); 926 927 /* get rid of anything on the idle list */ 928 ASSERT(fscp->fs_idleclean == 0); 929 cachefs_cnode_idleclean(fscp, 1); 930 if (fscp->fs_cnodecnt > 1) { 931 #ifdef CFSDEBUG 932 CFS_DEBUG(CFSDEBUG_VFSOP) 933 printf("cachefs_unmount: busy (cnode count %d)\n", 934 fscp->fs_cnodecnt); 935 #endif 936 error = EBUSY; 937 goto out; 938 } 939 940 fscache_hold(fscp); 941 942 /* get rid of the root cnode */ 943 if (cachefs_cnode_inactive(fscp->fs_rootvp, cr) == EBUSY) { 944 fscache_rele(fscp); 945 #ifdef CFSDEBUG 946 CFS_DEBUG(CFSDEBUG_VFSOP) 947 printf("cachefs_unmount: busy (inactive failed)\n"); 948 #endif 949 error = EBUSY; 950 goto out; 951 } 952 953 /* create the file indicating not mounted */ 954 attr.va_mode = S_IFREG | 0666; 955 attr.va_uid = 0; 956 attr.va_gid = 0; 957 attr.va_type = VREG; 958 attr.va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID; 959 if (fscp->fs_fscdirvp != NULL) 960 xx = VOP_CREATE(fscp->fs_fscdirvp, CACHEFS_UNMNT_FILE, &attr, 961 NONEXCL, 0600, &nmvp, kcred, 0, NULL, NULL); 962 else 963 xx = ENOENT; /* for unmounting when NOCACHE */ 964 if (xx == 0) { 965 VN_RELE(nmvp); 966 } else { 967 printf("could not create %s %d\n", CACHEFS_UNMNT_FILE, xx); 968 } 969 970 ASSERT(fscp->fs_cnodecnt == 0); 971 972 /* sync the file system just in case */ 973 fscache_sync(fscp); 974 975 /* lock out other unmounts and mount */ 976 mutex_enter(&cachefs_cachelock); 977 978 /* mark the file system as not mounted */ 979 mutex_enter(&fscp->fs_fslock); 980 fscp->fs_flags &= ~CFS_FS_MOUNTED; 981 fscp->fs_rootvp = NULL; 982 if (fscp->fs_kstat_id > 0) 983 cachefs_kstat_umount(fscp->fs_kstat_id); 984 fscp->fs_kstat_id = 0; 985 986 /* drop the inum translation table */ 987 if (fscp->fs_inum_size > 0) { 988 cachefs_kmem_free(fscp->fs_inum_trans, 989 fscp->fs_inum_size * sizeof (cachefs_inum_trans_t)); 990 fscp->fs_inum_size = 0; 991 fscp->fs_inum_trans = NULL; 992 fscp->fs_flags &= ~CFS_FS_HASHPRINT; 993 } 994 mutex_exit(&fscp->fs_fslock); 995 996 fscache_rele(fscp); 997 998 /* get rid of any unused fscache objects */ 999 mutex_enter(&cachep->c_fslistlock); 1000 fscache_list_gc(cachep); 1001 mutex_exit(&cachep->c_fslistlock); 1002 1003 /* get the number of mounts on this cache */ 1004 mutex_enter(&cachep->c_fslistlock); 1005 xx = fscache_list_mounted(cachep); 1006 mutex_exit(&cachep->c_fslistlock); 1007 1008 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_UMOUNT)) 1009 cachefs_log_umount(cachep, 0, vfsp); 1010 1011 /* if no mounts left, deactivate the cache */ 1012 if (xx == 0) 1013 cachefs_delete_cachep(cachep); 1014 1015 mutex_exit(&cachefs_cachelock); 1016 1017 out: 1018 if (error) { 1019 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_UMOUNT)) 1020 cachefs_log_umount(cachep, error, vfsp); 1021 } 1022 #ifdef CFSDEBUG 1023 CFS_DEBUG(CFSDEBUG_VFSOP) 1024 printf("cachefs_unmount: EXIT\n"); 1025 #endif 1026 return (error); 1027 } 1028 1029 /* 1030 * remove the cache from the list of caches 1031 */ 1032 1033 static void 1034 cachefs_delete_cachep(cachefscache_t *cachep) 1035 { 1036 struct cachefscache **cachepp; 1037 int found = 0; 1038 1039 ASSERT(MUTEX_HELD(&cachefs_cachelock)); 1040 1041 for (cachepp = &cachefs_cachelist; 1042 *cachepp != NULL; 1043 cachepp = &(*cachepp)->c_next) { 1044 if (*cachepp == cachep) { 1045 *cachepp = cachep->c_next; 1046 found++; 1047 break; 1048 } 1049 } 1050 ASSERT(found); 1051 1052 /* shut down the cache */ 1053 cachefs_cache_destroy(cachep); 1054 } 1055 1056 static int 1057 cachefs_root(vfs_t *vfsp, vnode_t **vpp) 1058 { 1059 /*LINTED alignment okay*/ 1060 struct fscache *fscp = (struct fscache *)vfsp->vfs_data; 1061 1062 ASSERT(fscp != NULL); 1063 ASSERT(fscp->fs_rootvp != NULL); 1064 1065 if (getzoneid() != GLOBAL_ZONEID) 1066 return (EPERM); 1067 *vpp = fscp->fs_rootvp; 1068 VN_HOLD(*vpp); 1069 return (0); 1070 } 1071 1072 /* 1073 * Get file system statistics. 1074 */ 1075 static int 1076 cachefs_statvfs(register vfs_t *vfsp, struct statvfs64 *sbp) 1077 { 1078 struct fscache *fscp = VFS_TO_FSCACHE(vfsp); 1079 struct cache_label *lp = &fscp->fs_cache->c_label; 1080 struct cache_usage *up = &fscp->fs_cache->c_usage; 1081 int error; 1082 1083 if (getzoneid() != GLOBAL_ZONEID) 1084 return (EPERM); 1085 error = cachefs_cd_access(fscp, 0, 0); 1086 if (error) 1087 return (error); 1088 1089 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) { 1090 /* 1091 * When connected return backfs stats 1092 */ 1093 error = VFS_STATVFS(fscp->fs_backvfsp, sbp); 1094 } else { 1095 /* 1096 * Otherwise, just return the frontfs stats 1097 */ 1098 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1099 error = VFS_STATVFS(fscp->fs_fscdirvp->v_vfsp, sbp); 1100 if (!error) { 1101 dev32_t d32; 1102 1103 sbp->f_frsize = MAXBSIZE; 1104 sbp->f_blocks = lp->cl_maxblks; 1105 sbp->f_bfree = sbp->f_bavail = 1106 lp->cl_maxblks - up->cu_blksused; 1107 sbp->f_files = lp->cl_maxinodes; 1108 sbp->f_ffree = sbp->f_favail = 1109 lp->cl_maxinodes - up->cu_filesused; 1110 (void) cmpldev(&d32, vfsp->vfs_dev); 1111 sbp->f_fsid = d32; 1112 } 1113 } 1114 cachefs_cd_release(fscp); 1115 if (error) 1116 return (error); 1117 1118 /* 1119 * Make sure fstype is CFS. 1120 */ 1121 (void) strcpy(sbp->f_basetype, vfssw[vfsp->vfs_fstype].vsw_name); 1122 bzero(sbp->f_fstr, sizeof (sbp->f_fstr)); 1123 1124 return (0); 1125 } 1126 1127 /* 1128 * queue a request to sync the given fscache 1129 */ 1130 static void 1131 queue_sync(struct cachefscache *cachep, cred_t *cr) 1132 { 1133 struct cachefs_req *rp; 1134 1135 rp = kmem_cache_alloc(cachefs_req_cache, KM_SLEEP); 1136 rp->cfs_cmd = CFS_CACHE_SYNC; 1137 rp->cfs_cr = cr; 1138 rp->cfs_req_u.cu_fs_sync.cf_cachep = cachep; 1139 crhold(rp->cfs_cr); 1140 cachefs_addqueue(rp, &cachep->c_workq); 1141 } 1142 1143 /*ARGSUSED*/ 1144 static int 1145 cachefs_sync(vfs_t *vfsp, short flag, cred_t *cr) 1146 { 1147 struct fscache *fscp; 1148 struct cachefscache *cachep; 1149 1150 if (getzoneid() != GLOBAL_ZONEID) 1151 return (EPERM); 1152 if (!(flag & SYNC_ATTR)) { 1153 /* 1154 * queue an async request to do the sync. 1155 * We always sync an entire cache (as opposed to an 1156 * individual fscache) so that we have an opportunity 1157 * to set the clean flag. 1158 */ 1159 if (vfsp) { 1160 /*LINTED alignment okay*/ 1161 fscp = (struct fscache *)vfsp->vfs_data; 1162 queue_sync(fscp->fs_cache, cr); 1163 } else { 1164 mutex_enter(&cachefs_cachelock); 1165 for (cachep = cachefs_cachelist; cachep != NULL; 1166 cachep = cachep->c_next) { 1167 queue_sync(cachep, cr); 1168 } 1169 mutex_exit(&cachefs_cachelock); 1170 } 1171 } 1172 return (0); 1173 } 1174 1175 static int 1176 cachefs_remount(struct vfs *vfsp, struct mounta *uap) 1177 { 1178 fscache_t *fscp = VFS_TO_FSCACHE(vfsp); 1179 cachefscache_t *cachep = fscp->fs_cache; 1180 int error = 0; 1181 STRUCT_DECL(cachefs_mountargs, map); 1182 struct cachefsoptions *cfs_options; 1183 char *backfs, *cacheid, *cachedir; 1184 struct vnode *cachedirvp = NULL; 1185 ino64_t fsid; 1186 vnode_t *backrootvp = NULL; 1187 struct vnode *tmpdirvp = NULL; 1188 1189 STRUCT_INIT(map, get_udatamodel()); 1190 error = copyin(uap->dataptr, STRUCT_BUF(map), 1191 SIZEOF_STRUCT(cachefs_mountargs, DATAMODEL_NATIVE)); 1192 if (error) 1193 goto out; 1194 1195 /* 1196 * get cache directory vp 1197 */ 1198 cachedir = (char *)STRUCT_FGETP(map, cfs_cachedir); 1199 error = lookupname(cachedir, UIO_USERSPACE, FOLLOW, 1200 NULLVPP, &cachedirvp); 1201 if (error) 1202 goto out; 1203 if (cachedirvp->v_type != VDIR) { 1204 error = EINVAL; 1205 goto out; 1206 } 1207 1208 error = 0; 1209 if (cachedirvp) { 1210 error = VOP_LOOKUP(cachedirvp, CACHEFS_DLOG_FILE, 1211 &tmpdirvp, NULL, 0, NULL, kcred, NULL, NULL, NULL); 1212 } 1213 cfs_options = (struct cachefsoptions *)STRUCT_FADDR(map, cfs_options); 1214 cacheid = (char *)STRUCT_FGETP(map, cfs_cacheid); 1215 /* XXX not quite right */ 1216 #if 0 1217 /* 1218 * If a log file exists and the cache is being mounted without 1219 * the snr (aka disconnectable) option, return an error. 1220 */ 1221 if ((error == 0) && 1222 !(cfs_options->opt_flags & CFS_DISCONNECTABLE)) { 1223 cmn_err(CE_WARN, 1224 "cachefs_mount: log exists and disconnectable" 1225 "option not specified\n"); 1226 error = EINVAL; 1227 goto out; 1228 } 1229 #endif 1230 error = 0; 1231 1232 /* 1233 * If the user is using NFSv4 and there are other options 1234 * specified, make sure we ignore the other options. 1235 */ 1236 if (CFS_ISFS_BACKFS_NFSV4(fscp)) { 1237 cfs_options->opt_flags = CFS_BACKFS_NFSV4; 1238 } 1239 1240 /* XXX need mount options "nocache" and "nofill" */ 1241 1242 /* if nocache is being turned off */ 1243 if (cachep->c_flags & CACHE_NOCACHE) { 1244 error = cachefs_cache_activate_ro(cachep, cachedirvp); 1245 if (error) 1246 goto out; 1247 cachefs_cache_activate_rw(cachep); 1248 1249 /* get the fsid for the fscache */ 1250 error = fscache_name_to_fsid(cachep, cacheid, &fsid); 1251 if (error) 1252 fsid = 0; 1253 1254 /* activate the fscache */ 1255 mutex_enter(&cachep->c_fslistlock); 1256 error = fscache_enable(fscp, fsid, cacheid, 1257 cfs_options, fscp->fs_info.fi_root); 1258 mutex_exit(&cachep->c_fslistlock); 1259 if (error) { 1260 cmn_err(CE_WARN, "cachefs: cannot remount %s\n", 1261 cacheid); 1262 goto out; 1263 } 1264 1265 /* enable the cache */ 1266 cachefs_enable_caching(fscp); 1267 fscache_activate_rw(fscp); 1268 } 1269 1270 /* else if nofill is being turn off */ 1271 else if (cachep->c_flags & CACHE_NOFILL) { 1272 ASSERT(cachep->c_flags & CACHE_NOFILL); 1273 cachefs_cache_activate_rw(cachep); 1274 1275 /* enable the cache */ 1276 cachefs_enable_caching(fscp); 1277 fscache_activate_rw(fscp); 1278 } 1279 1280 fscache_acset(fscp, STRUCT_FGET(map, cfs_acregmin), 1281 STRUCT_FGET(map, cfs_acregmax), 1282 STRUCT_FGET(map, cfs_acdirmin), STRUCT_FGET(map, cfs_acdirmax)); 1283 1284 /* if the backfs is mounted now or we have a new backfs */ 1285 backfs = (char *)STRUCT_FGETP(map, cfs_backfs); 1286 if (backfs && (cfs_options->opt_flags & CFS_SLIDE)) { 1287 /* get the back file system root vp */ 1288 error = lookupname(backfs, UIO_USERSPACE, FOLLOW, 1289 NULLVPP, &backrootvp); 1290 if (error) 1291 goto out; 1292 1293 /* 1294 * Make sure the thing we just looked up is a directory 1295 * and a root of a file system 1296 */ 1297 if (backrootvp->v_type != VDIR || 1298 !(backrootvp->v_flag & VROOT)) { 1299 cmn_err(CE_WARN, 1300 "cachefs_mount: backpath not a directory\n"); 1301 error = EINVAL; 1302 goto out; 1303 } 1304 1305 /* 1306 * XXX 1307 * Kind of dangerous to just set this but we do 1308 * not have locks around usage of fs_backvfsp. 1309 * Hope for the best for now. 1310 * Probably should also spin through vnodes and fix them up. 1311 * Krishna - fixed c_backvp to reflect the change. 1312 */ 1313 fscp->fs_backvfsp = backrootvp->v_vfsp; 1314 ((cnode_t *)(fscp->fs_rootvp->v_data))->c_backvp = backrootvp; 1315 1316 /* 1317 * Now the root cnode structure is an owner of 1318 * the opened back root vnode structure; we must 1319 * clear the pointer to back root vnode here as 1320 * we don't need it since now, and the root cnode 1321 * structure will control the vnode 1322 */ 1323 backrootvp = (vnode_t *)NULL; 1324 } 1325 1326 if (fscp->fs_kstat_id > 0) 1327 cachefs_kstat_umount(fscp->fs_kstat_id); 1328 fscp->fs_kstat_id = 0; 1329 cachefs_kstat_mount(fscp, uap->dir, backfs, cachedir, cacheid); 1330 1331 if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MOUNT)) 1332 cachefs_log_mount(cachep, error, vfsp, fscp, 1333 uap->dir, UIO_USERSPACE, 1334 (STRUCT_BUF(map) != NULL) ? cacheid : NULL); 1335 1336 out: 1337 if (cachedirvp) 1338 VN_RELE(cachedirvp); 1339 if (backrootvp) 1340 VN_RELE(backrootvp); 1341 return (error); 1342 }