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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 #include <sys/systm.h> 33 #include <sys/cred.h> 34 #include <sys/proc.h> 35 #include <sys/user.h> 36 #include <sys/vfs.h> 37 #include <sys/vnode.h> 38 #include <sys/pathname.h> 39 #include <sys/uio.h> 40 #include <sys/tiuser.h> 41 #include <sys/sysmacros.h> 42 #include <sys/kmem.h> 43 #include <sys/buf.h> 44 #include <netinet/in.h> 45 #include <rpc/types.h> 46 #include <rpc/xdr.h> 47 #include <rpc/auth.h> 48 #include <rpc/clnt.h> 49 #include <sys/mount.h> 50 #include <sys/ioctl.h> 51 #include <sys/statvfs.h> 52 #include <sys/errno.h> 53 #include <sys/debug.h> 54 #include <sys/cmn_err.h> 55 #include <sys/utsname.h> 56 #include <sys/modctl.h> 57 #include <vm/pvn.h> 58 59 #include <sys/fs/cachefs_fs.h> 60 61 /* 62 * cachefs_max_idle is a global that is tunable. 63 * This value decides how frequently or when the 64 * cachefs_cnode_idleclean is run. 65 * The default value is set to CFS_FS_MAXIDLE. 66 * The tunable if set to X triggers a cleanup when 67 * the number of idle cnodes reach X, and cleans up 68 * (.25 * X) idle cnodes. 69 */ 70 int cachefs_max_idle = CFS_FS_MAXIDLE; 71 72 73 struct kmem_cache *cachefs_cnode_cache = NULL; 74 75 /* 76 * Functions for cnode management. 77 */ 78 79 /* 80 * Puts cnode on idle list. Only call from an async thread or no 81 * locks held. 82 */ 83 /*ARGSUSED1*/ 84 void 85 cachefs_cnode_idle(struct vnode *vp, cred_t *cr) 86 { 87 cnode_t *cp = VTOC(vp); 88 fscache_t *fscp = C_TO_FSCACHE(cp); 89 int cleanidle; 90 vnode_t *unldvp; 91 cred_t *unlcred; 92 char *unlname; 93 int error; 94 95 /* 96 * The key to this routine is not to drop the vnode count 97 * while on the idle list. This prevents this routine from 98 * being called again by vn_rele on an inactive cnode. 99 * Nothing bad happens if an "active" cnode is put on the idle 100 * list. It eventually gets pulled off. 101 * Also this routine is only called from a thread message sent 102 * by cachefs_inactive(). It is not safe for this routine 103 * to be the "inactive" entry point because of the dnlc. 104 */ 105 106 for (;;) { 107 /* get access to the file system */ 108 error = cachefs_cd_access(fscp, 0, 1); 109 ASSERT(error == 0); 110 111 /* get exclusive access to this cnode */ 112 mutex_enter(&cp->c_statelock); 113 114 /* done with this loop if not unlinking a file */ 115 if (cp->c_unldvp == NULL) 116 break; 117 118 /* get unlink info out of the cnode */ 119 unldvp = cp->c_unldvp; 120 unlcred = cp->c_unlcred; 121 unlname = cp->c_unlname; 122 cp->c_unldvp = NULL; 123 cp->c_unlcred = NULL; 124 cp->c_unlname = NULL; 125 mutex_exit(&cp->c_statelock); 126 127 /* finish the remove operation */ 128 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) { 129 error = cachefs_remove_connected(unldvp, 130 unlname, unlcred, vp); 131 } else { 132 error = cachefs_remove_disconnected(unldvp, 133 unlname, unlcred, vp); 134 } 135 136 /* reaquire cnode lock */ 137 mutex_enter(&cp->c_statelock); 138 139 /* if a timeout occurred */ 140 if (CFS_TIMEOUT(fscp, error)) { 141 /* restore cnode state */ 142 if (cp->c_unldvp == NULL) { 143 cp->c_unldvp = unldvp; 144 cp->c_unlcred = unlcred; 145 cp->c_unlname = unlname; 146 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) { 147 mutex_exit(&cp->c_statelock); 148 cachefs_cd_release(fscp); 149 cachefs_cd_timedout(fscp); 150 continue; 151 } else { 152 cp->c_flags |= CN_PENDRM; 153 mutex_exit(&cp->c_statelock); 154 goto out; 155 } 156 } 157 } 158 /* free up resources */ 159 VN_RELE(unldvp); 160 cachefs_kmem_free(unlname, MAXNAMELEN); 161 crfree(unlcred); 162 break; 163 } 164 165 ASSERT((cp->c_flags & CN_IDLE) == 0); 166 /* 167 * If we are going to destroy this cnode, 168 * do it now instead of later. 169 */ 170 if (cp->c_flags & (CN_DESTROY | CN_STALE)) { 171 mutex_exit(&cp->c_statelock); 172 (void) cachefs_cnode_inactive(vp, cr); 173 goto out; 174 } 175 176 /* 177 * mark cnode as idle, put it on the idle list, and increment the 178 * number of idle cnodes 179 */ 180 cp->c_flags |= CN_IDLE; 181 mutex_enter(&fscp->fs_idlelock); 182 cachefs_cnode_idleadd(cp); 183 if ((fscp->fs_idlecnt > cachefs_max_idle) && 184 (fscp->fs_idleclean == 0) && 185 (fscp->fs_cdtransition == 0)) { 186 fscp->fs_idleclean = 1; 187 cleanidle = 1; 188 } else { 189 cleanidle = 0; 190 } 191 mutex_exit(&fscp->fs_idlelock); 192 193 /* release cnode */ 194 mutex_exit(&cp->c_statelock); 195 196 /* if should reduce the number of idle cnodes */ 197 if (cleanidle) { 198 ASSERT(fscp->fs_idlecnt > 1); 199 fscache_hold(fscp); 200 cachefs_cnode_idleclean(fscp, 0); 201 /* XXX race with cachefs_unmount() calling destroy */ 202 fscache_rele(fscp); 203 } 204 205 out: 206 /* release hold on the file system */ 207 /* XXX unmount() could have called destroy after fscache_rele() */ 208 cachefs_cd_release(fscp); 209 } 210 211 /* 212 * Removes cnodes from the idle list and destroys them. 213 */ 214 void 215 cachefs_cnode_idleclean(fscache_t *fscp, int unmount) 216 { 217 int remcnt; 218 cnode_t *cp; 219 220 mutex_enter(&fscp->fs_idlelock); 221 222 /* determine number of cnodes to destroy */ 223 if (unmount) { 224 /* destroy all plus any that go idle while in this routine */ 225 remcnt = fscp->fs_idlecnt * 2; 226 } else { 227 /* reduce to 75% of max allowed idle cnodes */ 228 remcnt = (fscp->fs_idlecnt - cachefs_max_idle) + 229 (cachefs_max_idle >> 2); 230 } 231 232 for (; remcnt > 0; remcnt--) { 233 /* get cnode on back of idle list and hold it */ 234 cp = fscp->fs_idleback; 235 if (cp == NULL) 236 break; 237 VN_HOLD(CTOV(cp)); 238 mutex_exit(&fscp->fs_idlelock); 239 240 /* if the cnode is still on the idle list */ 241 mutex_enter(&cp->c_statelock); 242 if (cp->c_flags & CN_IDLE) { 243 cp->c_flags &= ~CN_IDLE; 244 245 /* remove cnode from the idle list */ 246 mutex_enter(&fscp->fs_idlelock); 247 cachefs_cnode_idlerem(cp); 248 mutex_exit(&fscp->fs_idlelock); 249 mutex_exit(&cp->c_statelock); 250 251 /* destroy the cnode */ 252 VN_RELE(CTOV(cp)); 253 (void) cachefs_cnode_inactive(CTOV(cp), kcred); 254 } else { 255 /* cnode went active, just skip it */ 256 mutex_exit(&cp->c_statelock); 257 VN_RELE(CTOV(cp)); 258 } 259 mutex_enter(&fscp->fs_idlelock); 260 } 261 262 fscp->fs_idleclean = 0; 263 mutex_exit(&fscp->fs_idlelock); 264 } 265 266 /* 267 * This routine does the real work of inactivating a cachefs vnode. 268 */ 269 int 270 cachefs_cnode_inactive(register struct vnode *vp, cred_t *cr) 271 { 272 cnode_t *cp; 273 struct fscache *fscp; 274 struct filegrp *fgp; 275 cachefscache_t *cachep; 276 struct cachefs_metadata *mdp; 277 int meta_destroyed = 0; 278 279 cp = VTOC(vp); 280 281 fscp = C_TO_FSCACHE(cp); 282 cachep = fscp->fs_cache; 283 ASSERT(cachep != NULL); 284 fgp = cp->c_filegrp; 285 286 ASSERT((cp->c_flags & CN_IDLE) == 0); 287 288 /* truncate the front file if necessary */ 289 mutex_enter(&cp->c_statelock); 290 if ((cp->c_flags & CN_NOCACHE) && (cp->c_metadata.md_flags & MD_FILE) && 291 cp->c_metadata.md_frontblks) { 292 293 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 294 295 #ifdef CFSDEBUG 296 CFS_DEBUG(CFSDEBUG_INVALIDATE) 297 printf("c_cnode_inactive: invalidating %llu\n", 298 (u_longlong_t)cp->c_id.cid_fileno); 299 #endif 300 /* 301 * If the cnode is being populated, and we're not the 302 * populating thread, then block until the pop thread 303 * completes. If we are the pop thread, then we may come in 304 * here, but not to nuke the directory cnode at a critical 305 * juncture. 306 */ 307 while ((cp->c_flags & CN_ASYNC_POP_WORKING) && 308 (cp->c_popthrp != curthread)) 309 cv_wait(&cp->c_popcv, &cp->c_statelock); 310 311 cachefs_inval_object(cp); 312 } 313 mutex_exit(&cp->c_statelock); 314 315 for (;;) { 316 /* see if vnode is really inactive */ 317 mutex_enter(&vp->v_lock); 318 ASSERT(vp->v_count > 0); 319 if (vp->v_count > 1) { 320 /* 321 * It's impossible for us to be cnode_inactive for 322 * the root cnode _unless_ we are being called from 323 * cachefs_unmount (where inactive is called 324 * explictly). If the count is not 1, there is 325 * still an outstanding reference to the root cnode, 326 * and we return EBUSY; this allows cachefs_unmount 327 * to fail. 328 */ 329 if (cp->c_flags & CN_ROOT) { 330 mutex_exit(&vp->v_lock); 331 return (EBUSY); 332 } 333 cp->c_ipending = 0; 334 vp->v_count--; /* release our hold from vn_rele */ 335 mutex_exit(&vp->v_lock); 336 return (0); 337 } 338 mutex_exit(&vp->v_lock); 339 340 /* get rid of any pages, do not care if cannot be pushed */ 341 if (vn_has_cached_data(vp)) { 342 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 343 (void) cachefs_putpage_common(vp, (offset_t)0, 0, 344 B_INVAL | B_FORCE, cr); 345 } 346 347 /* if need to sync metadata, the call is a no op for NFSv4 */ 348 if ((cp->c_flags & (CN_UPDATED | CN_DESTROY)) == CN_UPDATED) { 349 (void) cachefs_sync_metadata(cp); 350 continue; 351 } 352 break; 353 } 354 355 /* 356 * Lock out possible race with makecachefsnode. 357 * Makecachefsnode will fix up the rl/active list stuff to 358 * be correct when it gets to run. 359 * We have to do the rl/active stuff while the cnode is on the hash 360 * list to sync actions on the rl/active list. 361 */ 362 mutex_enter(&fgp->fg_cnodelock); 363 mutex_enter(&cp->c_statelock); 364 365 /* see if vnode is still inactive */ 366 mutex_enter(&vp->v_lock); 367 ASSERT(vp->v_count > 0); 368 if (vp->v_count > 1) { 369 cp->c_ipending = 0; 370 vp->v_count--; 371 mutex_exit(&vp->v_lock); 372 mutex_exit(&cp->c_statelock); 373 mutex_exit(&fgp->fg_cnodelock); 374 #ifdef CFSDEBUG 375 CFS_DEBUG(CFSDEBUG_INVALIDATE) 376 printf("cachefs_cnode_inactive: %u vp %p\n", 377 vp->v_count, vp); 378 #endif 379 return (0); 380 } 381 mutex_exit(&vp->v_lock); 382 383 /* check for race with remove */ 384 if (cp->c_unldvp) { 385 mutex_exit(&cp->c_statelock); 386 mutex_exit(&fgp->fg_cnodelock); 387 388 /* this causes cachefs_inactive to be called again */ 389 VN_RELE(vp); 390 return (0); 391 } 392 393 /* if any pages left, really get rid of them */ 394 if (vn_has_cached_data(vp)) { 395 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 396 (void) pvn_vplist_dirty(vp, 0, NULL, B_INVAL | B_TRUNC, cr); 397 } 398 ASSERT(vp->v_count == 1); 399 400 mdp = &cp->c_metadata; 401 402 /* if we can (and should) destroy the front file and metadata */ 403 if ((cp->c_flags & (CN_DESTROY | CN_STALE)) && 404 (fgp->fg_flags & CFS_FG_WRITE) && !CFS_ISFS_BACKFS_NFSV4(fscp)) { 405 if (mdp->md_rlno) { 406 cachefs_removefrontfile(mdp, &cp->c_id, fgp); 407 cachefs_rlent_moveto(cachep, CACHEFS_RL_FREE, 408 mdp->md_rlno, 0); 409 mdp->md_rlno = 0; 410 mdp->md_rltype = CACHEFS_RL_NONE; 411 } 412 if ((cp->c_flags & CN_ALLOC_PENDING) == 0) { 413 (void) filegrp_destroy_metadata(fgp, &cp->c_id); 414 meta_destroyed = 1; 415 } 416 } 417 418 /* else put the front file on the gc list */ 419 else if (mdp->md_rlno && 420 (fgp->fg_flags & CFS_FG_WRITE) && 421 (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) { 422 #ifdef CFSDEBUG 423 cachefs_rlent_verify(cachep, CACHEFS_RL_ACTIVE, 424 mdp->md_rlno); 425 #endif /* CFSDEBUG */ 426 427 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 428 cachefs_rlent_moveto(cachep, CACHEFS_RL_GC, mdp->md_rlno, 429 mdp->md_frontblks); 430 mdp->md_rltype = CACHEFS_RL_GC; 431 cp->c_flags |= CN_UPDATED; 432 } 433 434 /* if idlelist pointer(s) not null, remove from idle list */ 435 if ((cp->c_idlefront != NULL) || (cp->c_idleback != NULL)) { 436 mutex_enter(&fscp->fs_idlelock); 437 cachefs_cnode_idlerem(cp); 438 mutex_exit(&fscp->fs_idlelock); 439 } 440 441 /* remove from the filegrp list prior to releasing the cnode lock */ 442 cachefs_cnode_listrem(cp); 443 444 mutex_exit(&cp->c_statelock); 445 if (! meta_destroyed) 446 (void) cachefs_sync_metadata(cp); 447 448 mutex_exit(&fgp->fg_cnodelock); 449 450 if (cp->c_cred != NULL) { 451 crfree(cp->c_cred); 452 cp->c_cred = NULL; 453 } 454 455 if (cp->c_frontvp) 456 VN_RELE(cp->c_frontvp); 457 458 if (cp->c_backvp) 459 VN_RELE(cp->c_backvp); 460 461 if (cp->c_acldirvp) 462 VN_RELE(cp->c_acldirvp); 463 464 rw_destroy(&cp->c_rwlock); 465 mutex_destroy(&cp->c_statelock); 466 cv_destroy(&cp->c_popcv); 467 mutex_destroy(&cp->c_iomutex); 468 cv_destroy(&cp->c_iocv); 469 470 /* free up cnode memory */ 471 vn_invalid(cp->c_vnode); 472 vn_free(cp->c_vnode); 473 kmem_cache_free(cachefs_cnode_cache, cp); 474 475 filegrp_rele(fgp); 476 (void) fscache_cnodecnt(fscp, -1); 477 return (0); 478 } 479 480 /* 481 * Add a cnode to the filegrp list. 482 */ 483 void 484 cachefs_cnode_listadd(struct cnode *cp) 485 { 486 filegrp_t *fgp = cp->c_filegrp; 487 488 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock)); 489 ASSERT(cp->c_next == NULL); 490 491 cp->c_next = fgp->fg_cnodelist; 492 fgp->fg_cnodelist = cp; 493 } 494 495 /* 496 * Remove a cnode from the filegrp list. 497 */ 498 void 499 cachefs_cnode_listrem(struct cnode *cp) 500 { 501 filegrp_t *fgp = cp->c_filegrp; 502 struct cnode **headpp; 503 504 #ifdef CFSDEBUG 505 int found = 0; 506 #endif 507 508 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock)); 509 ASSERT(cp->c_idleback == NULL); 510 ASSERT(cp->c_idlefront == NULL); 511 512 for (headpp = &fgp->fg_cnodelist; 513 *headpp != NULL; headpp = &(*headpp)->c_next) { 514 if (*headpp == cp) { 515 *headpp = cp->c_next; 516 cp->c_next = NULL; 517 #ifdef CFSDEBUG 518 found++; 519 #endif 520 break; 521 } 522 } 523 #ifdef CFSDEBUG 524 ASSERT(found); 525 #endif 526 } 527 528 /* 529 * Add a cnode to the front of the fscache idle list. 530 */ 531 void 532 cachefs_cnode_idleadd(struct cnode *cp) 533 { 534 fscache_t *fscp = C_TO_FSCACHE(cp); 535 536 ASSERT(MUTEX_HELD(&cp->c_statelock)); 537 ASSERT(MUTEX_HELD(&fscp->fs_idlelock)); 538 539 /* put cnode on the front of the idle list */ 540 cp->c_idlefront = fscp->fs_idlefront; 541 cp->c_idleback = NULL; 542 543 if (fscp->fs_idlefront) 544 fscp->fs_idlefront->c_idleback = cp; 545 else { 546 ASSERT(fscp->fs_idleback == NULL); 547 fscp->fs_idleback = cp; 548 } 549 fscp->fs_idlefront = cp; 550 fscp->fs_idlecnt++; 551 } 552 553 /* 554 * Remove a cnode from the fscache idle list. 555 */ 556 void 557 cachefs_cnode_idlerem(struct cnode *cp) 558 { 559 fscache_t *fscp = C_TO_FSCACHE(cp); 560 561 ASSERT(MUTEX_HELD(&cp->c_statelock)); 562 ASSERT(MUTEX_HELD(&fscp->fs_idlelock)); 563 564 if (cp->c_idlefront == NULL) { 565 ASSERT(fscp->fs_idleback == cp); 566 fscp->fs_idleback = cp->c_idleback; 567 if (fscp->fs_idleback != NULL) 568 fscp->fs_idleback->c_idlefront = NULL; 569 } else { 570 cp->c_idlefront->c_idleback = cp->c_idleback; 571 } 572 573 if (cp->c_idleback == NULL) { 574 ASSERT(fscp->fs_idlefront == cp); 575 fscp->fs_idlefront = cp->c_idlefront; 576 if (fscp->fs_idlefront != NULL) 577 fscp->fs_idlefront->c_idleback = NULL; 578 } else { 579 cp->c_idleback->c_idlefront = cp->c_idlefront; 580 cp->c_idleback = NULL; 581 } 582 cp->c_idlefront = NULL; 583 fscp->fs_idlecnt--; 584 ASSERT(fscp->fs_idlecnt >= 0); 585 } 586 587 /* 588 * Search the cnode list of the input file group, looking for a cnode which 589 * matches the supplied file ident fileno. 590 * 591 * Returns: 592 * *cpp = NULL, if no valid matching cnode is found 593 * *cpp = address of cnode with matching fileno, with c_statelock held 594 * return status is 0 if no cnode found, or if found & cookies match 595 * return status is 1 if a cnode was found, but the cookies don't match 596 * 597 * Note: must grab the c_statelock for each cnode, or its state could 598 * change while we're processing it. Also, if a cnode is found, must return 599 * with c_statelock still held, so that the cnode state cannot change until 600 * the calling routine releases the lock. 601 */ 602 int 603 cachefs_cnode_find(filegrp_t *fgp, cfs_cid_t *cidp, fid_t *cookiep, 604 struct cnode **cpp, struct vnode *backvp, vattr_t *vap) 605 { 606 struct cnode *cp; 607 int badcookie = 0; 608 uint32_t is_nfsv4; 609 610 #ifdef CFSDEBUG 611 CFS_DEBUG(CFSDEBUG_CNODE) 612 cmn_err(CE_NOTE, "cachefs_cnode_find: fileno %llu fgp %p\n", 613 (u_longlong_t)cidp->cid_fileno, (void *)fgp); 614 #endif 615 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock)); 616 617 *cpp = NULL; 618 is_nfsv4 = CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp); 619 620 /* 621 * Cookie should be filled unless disconnected operation or 622 * backfilesystem is NFSv4 623 */ 624 if (cookiep == NULL && !CFS_ISFS_SNR(fgp->fg_fscp) && 625 !CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) { 626 goto out; 627 } 628 629 for (cp = fgp->fg_cnodelist; cp != NULL; cp = cp->c_next) { 630 mutex_enter(&cp->c_statelock); 631 632 if ((cidp->cid_fileno != cp->c_id.cid_fileno && 633 (is_nfsv4 == FALSE || cp->c_backvp != backvp)) || 634 (cp->c_flags & (CN_STALE | CN_DESTROY))) { 635 mutex_exit(&cp->c_statelock); 636 continue; 637 } 638 639 /* 640 * Having found a non stale, non destroy pending cnode with 641 * matching fileno, will be exiting the for loop, after 642 * determining return status 643 */ 644 *cpp = cp; 645 646 if ((cookiep != NULL) && 647 ((cookiep->fid_len != cp->c_cookie.fid_len) || 648 (bcmp((caddr_t)cookiep->fid_data, 649 (caddr_t)&cp->c_cookie.fid_data, cookiep->fid_len)) != 0)) { 650 #ifdef CFSDEBUG 651 CFS_DEBUG(CFSDEBUG_GENERAL) { 652 cmn_err(CE_NOTE, 653 "cachefs: dup fileno %llu, cp %p\n", 654 (u_longlong_t)cidp->cid_fileno, (void *)cp); 655 } 656 #endif 657 badcookie = 1; 658 } 659 660 /* 661 * For NFSv4 since there is no fid, add a check to 662 * ensure the backvp and vap matches that in the cnode. 663 * If it doesn't then someone tried to use a stale cnode. 664 */ 665 if (is_nfsv4) { 666 if (backvp && backvp != cp->c_backvp || 667 vap && vap->va_type != cp->c_attr.va_type || 668 cidp->cid_fileno != cp->c_id.cid_fileno) { 669 CFS_DPRINT_BACKFS_NFSV4(C_TO_FSCACHE(cp), 670 ("cachefs_cnode_find (nfsv4): stale cnode " 671 "cnode %p, backvp %p, new-backvp %p, vap %p " 672 "fileno=%llx cp-fileno=%llx\n", 673 cp, cp->c_backvp, backvp, vap, 674 cidp->cid_fileno, cp->c_id.cid_fileno)); 675 badcookie = 1; 676 } 677 } 678 break; 679 } 680 out: 681 682 #ifdef CFSDEBUG 683 CFS_DEBUG(CFSDEBUG_CNODE) 684 cmn_err(CE_NOTE, "cachefs_cnode_find: cp %p\n", (void *)*cpp); 685 #endif 686 return (badcookie); 687 } 688 689 /* 690 * We have to initialize the cnode contents. Fill in the contents from the 691 * cache (attrcache file), from the info passed in, whatever it takes. 692 */ 693 static int 694 cachefs_cnode_init(cfs_cid_t *cidp, cnode_t *cp, fscache_t *fscp, 695 filegrp_t *fgp, fid_t *cookiep, vattr_t *vap, vnode_t *backvp, 696 int flag, cred_t *cr) 697 { 698 int error = 0; 699 int slotfound; 700 vnode_t *vp; 701 int null_cookie; 702 cachefscache_t *cachep = fscp->fs_cache; 703 704 bzero(cp, sizeof (cnode_t)); 705 cp->c_vnode = vn_alloc(KM_SLEEP); 706 707 vp = CTOV(cp); 708 709 vp->v_data = (caddr_t)cp; 710 711 rw_init(&cp->c_rwlock, NULL, RW_DEFAULT, NULL); 712 mutex_init(&cp->c_statelock, NULL, MUTEX_DEFAULT, NULL); 713 cv_init(&cp->c_popcv, NULL, CV_DEFAULT, NULL); 714 mutex_init(&cp->c_iomutex, NULL, MUTEX_DEFAULT, NULL); 715 cv_init(&cp->c_iocv, NULL, CV_DEFAULT, NULL); 716 717 vn_setops(vp, cachefs_getvnodeops()); 718 cp->c_id = *cidp; 719 if (backvp != NULL) { 720 cp->c_backvp = backvp; 721 VN_HOLD(backvp); 722 } 723 cp->c_flags |= flag; 724 filegrp_hold(fgp); 725 cp->c_filegrp = fgp; 726 if (cookiep) 727 cp->c_cookie = *cookiep; 728 mutex_enter(&cp->c_statelock); 729 730 /* 731 * if nocache is set then ignore anything cached for this file, 732 * if nfsv4 flag is set, then create the cnode but don't do 733 * any caching. 734 */ 735 if (cp->c_flags & CN_NOCACHE || CFS_ISFS_BACKFS_NFSV4(fscp)) { 736 /* 737 * this case only happens while booting without a cache 738 * or if NFSv4 is the backfilesystem 739 */ 740 ASSERT(!CFS_ISFS_SNR(fscp)); 741 ASSERT(fscp->fs_cdconnected == CFS_CD_CONNECTED); 742 if (cookiep || CFS_ISFS_BACKFS_NFSV4(fscp)) { 743 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr); 744 if (error) 745 goto out; 746 cp->c_flags |= CN_UPDATED | CN_ALLOC_PENDING; 747 ASSERT(cp->c_attr.va_type != 0); 748 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp, 749 cp->c_attr.va_type, cp->c_attr.va_rdev); 750 cachefs_cnode_setlocalstats(cp); 751 } else 752 error = ESTALE; 753 goto out; 754 } 755 756 /* 757 * see if there's a slot for this filegrp/cid fileno 758 * if not, and there's no cookie info, nothing can be done, but if 759 * there's cookie data indicate we need to create a metadata slot. 760 */ 761 slotfound = cachefs_cid_inuse(cp->c_filegrp, cidp); 762 if (slotfound == 0) { 763 if (cookiep == NULL) { 764 error = ENOENT; 765 goto out; 766 } 767 cp->c_flags |= CN_ALLOC_PENDING; 768 } else { 769 /* 770 * if a slot was found, then increment the slot in use count 771 * and try to read the metadata. 772 */ 773 cp->c_filegrp->fg_header->ach_count++; 774 error = filegrp_read_metadata(cp->c_filegrp, cidp, 775 &cp->c_metadata); 776 } 777 /* 778 * if there wasn't a slot, or an attempt to read it results in ENOENT, 779 * then init the cache object, create the vnode, etc... 780 */ 781 if ((slotfound == 0) || (error == ENOENT)) { 782 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr); 783 if (error) 784 goto out; 785 ASSERT(cp->c_attr.va_type != 0); 786 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp, 787 cp->c_attr.va_type, cp->c_attr.va_rdev); 788 cp->c_metadata.md_rltype = CACHEFS_RL_NONE; 789 } else if (error == 0) { 790 /* slot found, no error occurred on the metadata read */ 791 cp->c_size = cp->c_attr.va_size; 792 793 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) && 794 (cp->c_metadata.md_rlno != 0) && 795 (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) { 796 rl_entry_t rl, *rlp; 797 798 mutex_enter(&cachep->c_contentslock); 799 error = cachefs_rl_entry_get(cachep, 800 cp->c_metadata.md_rlno, &rlp); 801 if (error) { 802 mutex_exit(&cachep->c_contentslock); 803 goto out; 804 } 805 rl = *rlp; 806 mutex_exit(&cachep->c_contentslock); 807 if (cp->c_metadata.md_rltype != rl.rl_current) { 808 cp->c_flags |= CN_UPDATED; 809 cp->c_metadata.md_rltype = rl.rl_current; 810 } 811 } 812 813 /* 814 * If no cookie is specified, or if this is a local file, 815 * accept the one in the metadata. 816 */ 817 null_cookie = 0; 818 if ((cookiep == NULL) || (cp->c_id.cid_flags & CFS_CID_LOCAL)) { 819 cookiep = &cp->c_metadata.md_cookie; 820 null_cookie = 1; 821 } 822 823 /* if cookies do not match, reset the metadata */ 824 if ((cookiep->fid_len != cp->c_cookie.fid_len) || 825 (bcmp(&cookiep->fid_data, &cp->c_cookie.fid_data, 826 (size_t)cookiep->fid_len) != 0)) { 827 cp->c_cookie = *cookiep; 828 cp->c_flags |= CN_UPDATED; 829 cp->c_metadata.md_timestamp.tv_sec = 0; 830 /* clear all but the front file bit */ 831 cp->c_metadata.md_flags &= MD_FILE; 832 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr); 833 ASSERT(cp->c_attr.va_type != 0); 834 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp, 835 cp->c_attr.va_type, cp->c_attr.va_rdev); 836 } 837 838 /* else if the consistency type changed, fix it up */ 839 else if (cp->c_metadata.md_consttype != fscp->fs_consttype) { 840 ASSERT(cp->c_attr.va_type != 0); 841 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp, 842 cp->c_attr.va_type, cp->c_attr.va_rdev); 843 CFSOP_CONVERT_COBJECT(fscp, cp, cr); 844 if (!null_cookie) { 845 error = CFSOP_CHECK_COBJECT(fscp, cp, 846 C_BACK_CHECK, cr); 847 } 848 } 849 850 /* else check the consistency of the data */ 851 else { 852 ASSERT(cp->c_attr.va_type != 0); 853 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp, 854 cp->c_attr.va_type, cp->c_attr.va_rdev); 855 if (!null_cookie) { 856 error = CFSOP_CHECK_COBJECT(fscp, cp, 0, cr); 857 } 858 } 859 } else { 860 goto out; 861 } 862 cachefs_cnode_setlocalstats(cp); 863 864 out: 865 mutex_exit(&cp->c_statelock); 866 if (error) { 867 if (cp->c_frontvp) 868 VN_RELE(cp->c_frontvp); 869 if (cp->c_backvp) 870 VN_RELE(cp->c_backvp); 871 if (cp->c_acldirvp) 872 VN_RELE(cp->c_acldirvp); 873 filegrp_rele(fgp); 874 rw_destroy(&cp->c_rwlock); 875 mutex_destroy(&cp->c_statelock); 876 cv_destroy(&cp->c_popcv); 877 mutex_destroy(&cp->c_iomutex); 878 cv_destroy(&cp->c_iocv); 879 } 880 return (error); 881 } 882 883 /* 884 * Finds the cnode for the specified fileno and fid. 885 * Creates the cnode if it does not exist. 886 * The cnode is returned held. 887 */ 888 int 889 cachefs_cnode_make(cfs_cid_t *cidp, fscache_t *fscp, fid_t *cookiep, 890 vattr_t *vap, vnode_t *backvp, cred_t *cr, int flag, cnode_t **cpp) 891 { 892 struct cnode *cp; 893 int error; 894 struct filegrp *fgp; 895 struct cachefs_metadata *mdp; 896 fid_t cookie; 897 898 #ifdef CFSDEBUG 899 CFS_DEBUG(CFSDEBUG_CNODE) 900 printf("cachefs_cnode_make: ENTER fileno %llu\n", 901 (u_longlong_t)cidp->cid_fileno); 902 #endif 903 904 /* get the file group that owns this file */ 905 mutex_enter(&fscp->fs_fslock); 906 fgp = filegrp_list_find(fscp, cidp); 907 if (fgp == NULL) { 908 fgp = filegrp_create(fscp, cidp); 909 filegrp_list_add(fscp, fgp); 910 } 911 filegrp_hold(fgp); 912 mutex_exit(&fscp->fs_fslock); 913 914 /* grab the cnode list lock */ 915 mutex_enter(&fgp->fg_cnodelock); 916 917 if ((fgp->fg_flags & CFS_FG_READ) == 0) 918 flag |= CN_NOCACHE; 919 920 error = 0; 921 cp = NULL; 922 923 /* look for the cnode on the cnode list */ 924 error = cachefs_cnode_find(fgp, cidp, cookiep, &cp, backvp, vap); 925 926 /* 927 * If there already is a cnode with this cid but a different cookie, 928 * (or backvp) we're not going to be using the one we found. 929 */ 930 if (error && CFS_ISFS_BACKFS_NFSV4(fscp)) { 931 ASSERT(MUTEX_HELD(&cp->c_statelock)); 932 cachefs_cnode_stale(cp); 933 mutex_exit(&cp->c_statelock); 934 cp = NULL; 935 error = 0; 936 } else if (error) { 937 ASSERT(cp); 938 ASSERT(cookiep); 939 940 mutex_exit(&cp->c_statelock); 941 942 /* 943 * If backvp is NULL then someone tried to use 944 * a stale cookie. 945 */ 946 if (backvp == NULL) { 947 mutex_exit(&fgp->fg_cnodelock); 948 error = ESTALE; 949 goto out; 950 } 951 952 /* verify the backvp */ 953 error = cachefs_getcookie(backvp, &cookie, NULL, cr, TRUE); 954 if (error || 955 ((cookiep->fid_len != cookie.fid_len) || 956 (bcmp(&cookiep->fid_data, cookie.fid_data, 957 (size_t)cookiep->fid_len) != 0))) { 958 mutex_exit(&fgp->fg_cnodelock); 959 error = ESTALE; 960 goto out; 961 } 962 963 /* make the old cnode give up its front file resources */ 964 VN_HOLD(CTOV(cp)); 965 (void) cachefs_sync_metadata(cp); 966 mutex_enter(&cp->c_statelock); 967 mdp = &cp->c_metadata; 968 if (mdp->md_rlno) { 969 /* XXX sam: should this assert be NOCACHE? */ 970 /* XXX sam: maybe we should handle NOFILL as no-op */ 971 ASSERT((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0); 972 973 /* if modified in the cache, move to lost+found */ 974 if ((cp->c_attr.va_type == VREG) && 975 (cp->c_metadata.md_rltype == CACHEFS_RL_MODIFIED)) { 976 error = cachefs_cnode_lostfound(cp, NULL); 977 if (error) { 978 mutex_exit(&cp->c_statelock); 979 VN_RELE(CTOV(cp)); 980 mutex_exit(&fgp->fg_cnodelock); 981 error = ESTALE; 982 goto out; 983 } 984 } 985 986 /* else nuke the front file */ 987 else { 988 cachefs_cnode_stale(cp); 989 } 990 } else { 991 cachefs_cnode_stale(cp); 992 } 993 mutex_exit(&cp->c_statelock); 994 VN_RELE(CTOV(cp)); 995 cp = NULL; 996 error = 0; 997 } 998 999 1000 /* if the cnode does not exist */ 1001 if (cp == NULL) { 1002 /* XXX should we drop all locks for this? */ 1003 cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP); 1004 1005 error = cachefs_cnode_init(cidp, cp, fscp, fgp, 1006 cookiep, vap, backvp, flag, cr); 1007 if (error) { 1008 mutex_exit(&fgp->fg_cnodelock); 1009 vn_free(cp->c_vnode); 1010 kmem_cache_free(cachefs_cnode_cache, cp); 1011 goto out; 1012 } 1013 1014 if (cp->c_metadata.md_rlno && 1015 (cp->c_metadata.md_rltype == CACHEFS_RL_GC) && 1016 ((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0)) { 1017 #ifdef CFSDEBUG 1018 cachefs_rlent_verify(fscp->fs_cache, 1019 CACHEFS_RL_GC, cp->c_metadata.md_rlno); 1020 #endif /* CFSDEBUG */ 1021 cachefs_rlent_moveto(fscp->fs_cache, 1022 CACHEFS_RL_ACTIVE, cp->c_metadata.md_rlno, 1023 cp->c_metadata.md_frontblks); 1024 cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE; 1025 cp->c_flags |= CN_UPDATED; 1026 } 1027 1028 cachefs_cnode_listadd(cp); 1029 vn_exists(cp->c_vnode); 1030 mutex_exit(&fgp->fg_cnodelock); 1031 (void) fscache_cnodecnt(fscp, 1); 1032 } 1033 1034 /* else if the cnode exists */ 1035 else { 1036 VN_HOLD(CTOV(cp)); 1037 1038 /* remove from idle list if on it */ 1039 if (cp->c_flags & CN_IDLE) { 1040 cp->c_flags &= ~CN_IDLE; 1041 1042 mutex_enter(&fscp->fs_idlelock); 1043 cachefs_cnode_idlerem(cp); 1044 mutex_exit(&fscp->fs_idlelock); 1045 VN_RELE(CTOV(cp)); 1046 cp->c_ipending = 0; 1047 } 1048 mutex_exit(&cp->c_statelock); 1049 mutex_exit(&fgp->fg_cnodelock); 1050 } 1051 1052 /* 1053 * Assertion to ensure the cnode matches 1054 * the backvp and attribute type information. 1055 */ 1056 ASSERT((CFS_ISFS_BACKFS_NFSV4(fscp) == 0) || 1057 ((cp->c_backvp == backvp) && 1058 (cp->c_attr.va_type == vap->va_type))); 1059 out: 1060 *cpp = ((error == 0) ? cp : NULL); 1061 filegrp_rele(fgp); 1062 1063 #ifdef CFSDEBUG 1064 CFS_DEBUG(CFSDEBUG_CNODE) 1065 printf("cachefs_cnode_make: EXIT cp %p, error %d\n", 1066 (void *)*cpp, error); 1067 #endif 1068 return (error); 1069 } 1070 1071 /* 1072 * cachefs_cid_inuse() 1073 * 1074 * returns nonzero if a cid has any data in the cache; either a cnode 1075 * or metadata. 1076 */ 1077 1078 int 1079 cachefs_cid_inuse(filegrp_t *fgp, cfs_cid_t *cidp) 1080 { 1081 cnode_t *cp; 1082 int status = 0; 1083 1084 ASSERT(MUTEX_HELD(&fgp->fg_cnodelock)); 1085 1086 /* 1087 * Since we don't care about the cookie data, we don't care about any 1088 * status that find might return. 1089 */ 1090 1091 cp = NULL; 1092 (void) cachefs_cnode_find(fgp, cidp, NULL, &cp, NULL, NULL); 1093 if (cp != NULL) { 1094 mutex_exit(&cp->c_statelock); 1095 status = 1; 1096 return (status); 1097 } 1098 1099 /* 1100 * Don't want to use filegrp_read_metadata, since it will return 1101 * ENOENT if the metadata slot exists but hasn't been written to yet. 1102 * That condition still counts as the slot (metadata) being in use. 1103 * Instead, as long as the filegrp attrcache has been created and 1104 * there's a slot assigned for this cid, then the metadata is in use. 1105 */ 1106 if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) && 1107 (filegrp_cid_to_slot(fgp, cidp) != 0)) 1108 status = 1; 1109 1110 return (status); 1111 } 1112 1113 /* 1114 * cachefs_fileno_inuse() 1115 * 1116 * returns nonzero if a fileno is known to the cache, as either a 1117 * local or a normal file. 1118 */ 1119 1120 int 1121 cachefs_fileno_inuse(fscache_t *fscp, ino64_t fileno) 1122 { 1123 cfs_cid_t cid; 1124 filegrp_t *fgp; 1125 int known = 0; 1126 1127 ASSERT(MUTEX_HELD(&fscp->fs_fslock)); 1128 cid.cid_fileno = fileno; 1129 1130 /* if there's no filegrp for this cid range, then there's no data */ 1131 fgp = filegrp_list_find(fscp, &cid); 1132 if (fgp == NULL) 1133 return (known); 1134 1135 filegrp_hold(fgp); 1136 mutex_enter(&fgp->fg_cnodelock); 1137 1138 cid.cid_flags = CFS_CID_LOCAL; 1139 if (cachefs_cid_inuse(fgp, &cid)) { 1140 known = 1; 1141 goto out; 1142 } 1143 cid.cid_flags = 0; 1144 if (cachefs_cid_inuse(fgp, &cid)) 1145 known = 1; 1146 out: 1147 mutex_exit(&fgp->fg_cnodelock); 1148 filegrp_rele(fgp); 1149 return (known); 1150 } 1151 1152 /* 1153 * Creates a cnode from an unused inode in the cache. 1154 * The cnode is returned held. 1155 */ 1156 int 1157 cachefs_cnode_create(fscache_t *fscp, vattr_t *vap, int flag, cnode_t **cpp) 1158 { 1159 struct cnode *cp; 1160 int error, found; 1161 struct filegrp *fgp; 1162 cfs_cid_t cid, cid2; 1163 1164 ASSERT(CFS_ISFS_SNR(fscp)); 1165 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1166 1167 cid.cid_flags = CFS_CID_LOCAL; 1168 cid2.cid_flags = 0; 1169 1170 /* find an unused local file in the cache */ 1171 for (;;) { 1172 mutex_enter(&fscp->fs_fslock); 1173 1174 /* make sure we did not wrap */ 1175 fscp->fs_info.fi_localfileno++; 1176 if (fscp->fs_info.fi_localfileno == 0) 1177 fscp->fs_info.fi_localfileno = 3; 1178 cid.cid_fileno = fscp->fs_info.fi_localfileno; 1179 fscp->fs_flags |= CFS_FS_DIRTYINFO; 1180 1181 /* avoid fileno conflict in non-local space */ 1182 cid2.cid_fileno = cid.cid_fileno; 1183 fgp = filegrp_list_find(fscp, &cid2); 1184 if (fgp != NULL) { 1185 filegrp_hold(fgp); 1186 mutex_enter(&fgp->fg_cnodelock); 1187 found = cachefs_cid_inuse(fgp, &cid2); 1188 mutex_exit(&fgp->fg_cnodelock); 1189 filegrp_rele(fgp); 1190 if (found) { 1191 mutex_exit(&fscp->fs_fslock); 1192 continue; 1193 } 1194 } 1195 1196 /* get the file group that owns this fileno */ 1197 fgp = filegrp_list_find(fscp, &cid); 1198 if (fgp == NULL) { 1199 fgp = filegrp_create(fscp, &cid); 1200 filegrp_list_add(fscp, fgp); 1201 } 1202 1203 /* see if there is any room left in this file group */ 1204 mutex_enter(&fgp->fg_mutex); 1205 if (fgp->fg_header && 1206 (fgp->fg_header->ach_count == 1207 fscp->fs_info.fi_fgsize)) { 1208 /* no more room, set up for the next file group */ 1209 fscp->fs_info.fi_localfileno = fgp->fg_id.cid_fileno + 1210 fscp->fs_info.fi_fgsize; 1211 mutex_exit(&fgp->fg_mutex); 1212 mutex_exit(&fscp->fs_fslock); 1213 continue; 1214 } 1215 mutex_exit(&fgp->fg_mutex); 1216 1217 filegrp_hold(fgp); 1218 mutex_exit(&fscp->fs_fslock); 1219 1220 ASSERT((fgp->fg_flags & 1221 (CFS_FG_READ | CFS_FG_WRITE)) == 1222 (CFS_FG_READ | CFS_FG_WRITE)); 1223 1224 /* grab the cnode list lock */ 1225 mutex_enter(&fgp->fg_cnodelock); 1226 1227 if ((fgp->fg_flags & CFS_FG_READ) == 0) 1228 flag |= CN_NOCACHE; 1229 1230 /* keep looking if a cnode or metadata exist for this fileno */ 1231 if (cachefs_cid_inuse(fgp, &cid)) { 1232 mutex_exit(&fgp->fg_cnodelock); 1233 filegrp_rele(fgp); 1234 #ifdef CFSDEBUG 1235 CFS_DEBUG(CFSDEBUG_CNODE) 1236 cmn_err(CE_NOTE, "cachefs_cnode_create: " 1237 "fileno %llu exists.\n", 1238 (u_longlong_t)cid.cid_fileno); 1239 #endif 1240 continue; 1241 } 1242 break; 1243 } 1244 1245 vap->va_nodeid = cid.cid_fileno; 1246 1247 /* create space for the cnode */ 1248 cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP); 1249 1250 /* set up the cnode */ 1251 error = cachefs_cnode_init(&cid, cp, fscp, fgp, 1252 &cp->c_cookie, vap, NULL, flag, kcred); 1253 if (error) { 1254 mutex_exit(&fgp->fg_cnodelock); 1255 vn_free(cp->c_vnode); 1256 kmem_cache_free(cachefs_cnode_cache, cp); 1257 goto out; 1258 } 1259 1260 /* save copy of fileno that is returned to the user */ 1261 cp->c_metadata.md_flags |= MD_LOCALFILENO; 1262 cp->c_metadata.md_localfileno = cid.cid_fileno; 1263 cp->c_flags |= CN_UPDATED; 1264 1265 cachefs_cnode_listadd(cp); 1266 mutex_exit(&fgp->fg_cnodelock); 1267 (void) fscache_cnodecnt(fscp, 1); 1268 1269 out: 1270 *cpp = ((error == 0) ? cp : NULL); 1271 filegrp_rele(fgp); 1272 return (error); 1273 } 1274 1275 /* 1276 * Moves the cnode to its new location in the cache. 1277 * Before calling this routine other steps must be taken 1278 * to ensure that other file system routines that operate 1279 * on cnodes do not run. 1280 */ 1281 void 1282 cachefs_cnode_move(cnode_t *cp) 1283 { 1284 fscache_t *fscp = C_TO_FSCACHE(cp); 1285 cfs_cid_t cid; 1286 filegrp_t *fgp; 1287 filegrp_t *ofgp = cp->c_filegrp; 1288 struct cachefs_metadata *mdp; 1289 cnode_t *xcp; 1290 char oname[CFS_FRONTFILE_NAME_SIZE]; 1291 char nname[CFS_FRONTFILE_NAME_SIZE]; 1292 int ffnuke = 0; 1293 int error; 1294 1295 ASSERT(CFS_ISFS_SNR(fscp)); 1296 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1297 ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL); 1298 ASSERT(cp->c_attr.va_nodeid != 0); 1299 1300 /* construct the cid of the new file location */ 1301 cid.cid_fileno = cp->c_attr.va_nodeid; 1302 cid.cid_flags = 0; 1303 1304 /* see if there already is a file occupying our slot */ 1305 error = cachefs_cnode_make(&cid, fscp, NULL, NULL, NULL, kcred, 1306 0, &xcp); 1307 if (error == 0) { 1308 mutex_enter(&xcp->c_statelock); 1309 cachefs_cnode_stale(xcp); 1310 mutex_exit(&xcp->c_statelock); 1311 VN_RELE(CTOV(xcp)); 1312 xcp = NULL; 1313 error = 0; 1314 } 1315 1316 /* get the file group that this file is moving to */ 1317 mutex_enter(&fscp->fs_fslock); 1318 fgp = filegrp_list_find(fscp, &cid); 1319 if (fgp == NULL) { 1320 fgp = filegrp_create(fscp, &cid); 1321 filegrp_list_add(fscp, fgp); 1322 } 1323 filegrp_hold(fgp); 1324 mutex_exit(&fscp->fs_fslock); 1325 1326 /* XXX fix to not have to create metadata to hold rl slot */ 1327 /* get a metadata slot in the new file group */ 1328 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 1329 (void) filegrp_allocattr(fgp); 1330 } 1331 /* XXX can fix create_metadata to call allocattr if necessary? */ 1332 error = filegrp_create_metadata(fgp, &cp->c_metadata, &cid); 1333 if (error) 1334 ffnuke = 1; 1335 if ((ffnuke == 0) && filegrp_ffhold(fgp)) 1336 ffnuke = 1; 1337 1338 /* move the front file to the new file group */ 1339 if ((ffnuke == 0) && (cp->c_metadata.md_flags & MD_FILE)) { 1340 make_ascii_name(&cp->c_id, oname); 1341 make_ascii_name(&cid, nname); 1342 error = VOP_RENAME(ofgp->fg_dirvp, oname, fgp->fg_dirvp, 1343 nname, kcred); 1344 if (error) { 1345 ffnuke = 1; 1346 #ifdef CFSDEBUG 1347 if (error != ENOSPC) { 1348 CFS_DEBUG(CFSDEBUG_CNODE) 1349 printf("cachefs: cnode_move " 1350 "1: error %d\n", error); 1351 } 1352 #endif 1353 } 1354 } 1355 1356 /* remove the file from the old file group */ 1357 mutex_enter(&ofgp->fg_cnodelock); 1358 mutex_enter(&cp->c_statelock); 1359 if (cp->c_frontvp) { 1360 VN_RELE(cp->c_frontvp); 1361 cp->c_frontvp = NULL; 1362 } 1363 if (cp->c_acldirvp) { 1364 VN_RELE(cp->c_acldirvp); 1365 cp->c_acldirvp = NULL; 1366 } 1367 mdp = &cp->c_metadata; 1368 if (mdp->md_rlno) { 1369 if (ffnuke) { 1370 cachefs_removefrontfile(mdp, &cp->c_id, ofgp); 1371 cachefs_rlent_moveto(fscp->fs_cache, 1372 CACHEFS_RL_FREE, mdp->md_rlno, 0); 1373 mdp->md_rlno = 0; 1374 mdp->md_rltype = CACHEFS_RL_NONE; 1375 } else { 1376 filegrp_ffrele(ofgp); 1377 } 1378 } 1379 if (ffnuke) 1380 mdp->md_flags &= ~MD_PACKED; 1381 if ((cp->c_flags & CN_ALLOC_PENDING) == 0) { 1382 (void) filegrp_destroy_metadata(ofgp, &cp->c_id); 1383 cp->c_flags |= CN_ALLOC_PENDING; 1384 } 1385 cachefs_cnode_listrem(cp); 1386 cp->c_filegrp = NULL; 1387 mutex_exit(&cp->c_statelock); 1388 mutex_exit(&ofgp->fg_cnodelock); 1389 1390 /* add the cnode to the new file group */ 1391 mutex_enter(&fgp->fg_cnodelock); 1392 mutex_enter(&cp->c_statelock); 1393 cp->c_id = cid; 1394 cp->c_filegrp = fgp; 1395 cp->c_flags |= CN_UPDATED; 1396 mutex_exit(&cp->c_statelock); 1397 cachefs_cnode_listadd(cp); 1398 if (mdp->md_rlno) 1399 cachefs_rl_changefileno(fscp->fs_cache, mdp->md_rlno, 1400 cp->c_id.cid_fileno); 1401 mutex_exit(&fgp->fg_cnodelock); 1402 1403 filegrp_rele(ofgp); 1404 } 1405 1406 /* 1407 * Syncs out the specified cnode. 1408 * Only called via cnode_traverse from fscache_sync 1409 */ 1410 void 1411 cachefs_cnode_sync(cnode_t *cp) 1412 { 1413 vnode_t *vp = CTOV(cp); 1414 int error = 0; 1415 fscache_t *fscp = C_TO_FSCACHE(cp); 1416 int held = 0; 1417 1418 if (cp->c_flags & (CN_STALE | CN_DESTROY)) 1419 return; 1420 1421 if (fscp->fs_backvfsp && fscp->fs_backvfsp->vfs_flag & VFS_RDONLY) 1422 return; 1423 1424 for (;;) { 1425 /* get (or renew) access to the file system */ 1426 if (held) { 1427 cachefs_cd_release(fscp); 1428 held = 0; 1429 } 1430 /* 1431 * Getting file system access for reading is really cheating. 1432 * However we are getting called from sync so we do not 1433 * want to hang up if the cachefsd is not running. 1434 */ 1435 error = cachefs_cd_access(fscp, 0, 0); 1436 if (error) 1437 break; 1438 held = 1; 1439 1440 /* if a regular file, write out the pages */ 1441 if ((vp->v_type == VREG) && vn_has_cached_data(vp)) { 1442 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1443 error = cachefs_putpage_common(vp, (offset_t)0, 1444 0, 0, kcred); 1445 if (CFS_TIMEOUT(fscp, error)) { 1446 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) { 1447 cachefs_cd_release(fscp); 1448 held = 0; 1449 cachefs_cd_timedout(fscp); 1450 continue; 1451 } else { 1452 /* cannot push, give up */ 1453 break; 1454 } 1455 } 1456 1457 /* clear the cnode error if putpage worked */ 1458 if ((error == 0) && cp->c_error) { 1459 mutex_enter(&cp->c_statelock); 1460 cp->c_error = 0; 1461 mutex_exit(&cp->c_statelock); 1462 } 1463 1464 if (error) 1465 break; 1466 } 1467 1468 /* if connected, sync the backvp */ 1469 if ((fscp->fs_cdconnected == CFS_CD_CONNECTED) && 1470 cp->c_backvp) { 1471 mutex_enter(&cp->c_statelock); 1472 if (cp->c_backvp) { 1473 error = VOP_FSYNC(cp->c_backvp, FSYNC, kcred); 1474 if (CFS_TIMEOUT(fscp, error)) { 1475 mutex_exit(&cp->c_statelock); 1476 cachefs_cd_release(fscp); 1477 held = 0; 1478 cachefs_cd_timedout(fscp); 1479 continue; 1480 } else if (error && (error != EINTR)) 1481 cp->c_error = error; 1482 } 1483 mutex_exit(&cp->c_statelock); 1484 } 1485 1486 /* sync the metadata and the front file to the front fs */ 1487 (void) cachefs_sync_metadata(cp); 1488 break; 1489 } 1490 1491 if (held) 1492 cachefs_cd_release(fscp); 1493 } 1494 1495 /* 1496 * Moves the specified file to the lost+found directory for the 1497 * cached file system. 1498 * Invalidates cached data and attributes. 1499 * Returns 0 or an error if could not perform operation. 1500 */ 1501 int 1502 cachefs_cnode_lostfound(cnode_t *cp, char *rname) 1503 { 1504 int error = 0; 1505 fscache_t *fscp; 1506 cachefscache_t *cachep; 1507 char oname[CFS_FRONTFILE_NAME_SIZE]; 1508 filegrp_t *fgp; 1509 char *namep, *strp; 1510 char *namebuf = NULL; 1511 vnode_t *nvp; 1512 int index; 1513 int len; 1514 1515 fscp = C_TO_FSCACHE(cp); 1516 cachep = fscp->fs_cache; 1517 1518 ASSERT(MUTEX_HELD(&cp->c_statelock)); 1519 ASSERT((cachep->c_flags & (CACHE_NOCACHE|CACHE_NOFILL)) == 0); 1520 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1521 1522 fgp = cp->c_filegrp; 1523 1524 /* set up the file group if necessary */ 1525 if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) { 1526 error = filegrp_allocattr(fgp); 1527 if (error) 1528 goto out; 1529 } 1530 ASSERT(fgp->fg_dirvp); 1531 1532 namebuf = cachefs_kmem_alloc(MAXNAMELEN * 2, KM_SLEEP); 1533 1534 if ((cp->c_attr.va_type != VREG) || 1535 (cp->c_metadata.md_rltype != CACHEFS_RL_MODIFIED) || 1536 ((cp->c_metadata.md_flags & MD_POPULATED) == 0) || 1537 ((cp->c_metadata.md_flags & MD_FILE) == 0) || 1538 (cp->c_metadata.md_rlno == 0)) { 1539 #ifdef CFSDEBUG 1540 CFS_DEBUG(CFSDEBUG_CNODE) 1541 printf("cachefs_cnode_lostfound cp %p cannot save\n", 1542 (void *)cp); 1543 #endif 1544 error = EINVAL; 1545 goto out; 1546 } 1547 1548 /* lock out other users of the lost+found directory */ 1549 mutex_enter(&cachep->c_contentslock); 1550 1551 /* find a name we can use in lost+found */ 1552 if (rname) 1553 namep = rname; 1554 else 1555 namep = "lostfile"; 1556 error = VOP_LOOKUP(cachep->c_lostfoundvp, namep, &nvp, 1557 NULL, 0, NULL, kcred); 1558 if (error == 0) 1559 VN_RELE(nvp); 1560 if (error != ENOENT) { 1561 #define MAXTRIES 1000 1562 strp = namep; 1563 for (index = 0; index < MAXTRIES; index++) { 1564 (void) sprintf(namebuf, "%s.%" PRIx64, strp, 1565 gethrestime_sec() * cp->c_id.cid_fileno * index); 1566 len = (int)strlen(namebuf) + 1; 1567 if (len > MAXNAMELEN) 1568 namep = &namebuf[len - MAXNAMELEN]; 1569 else 1570 namep = namebuf; 1571 error = VOP_LOOKUP(cachep->c_lostfoundvp, namep, &nvp, 1572 NULL, 0, NULL, kcred); 1573 if (error == 0) 1574 VN_RELE(nvp); 1575 if (error == ENOENT) 1576 break; 1577 } 1578 if (index == MAXTRIES) { 1579 error = EIO; 1580 mutex_exit(&cachep->c_contentslock); 1581 goto out; 1582 } 1583 } 1584 1585 /* get the name of the front file */ 1586 make_ascii_name(&cp->c_id, oname); 1587 1588 /* rename the file into the lost+found directory */ 1589 error = VOP_RENAME(fgp->fg_dirvp, oname, cachep->c_lostfoundvp, 1590 namep, kcred); 1591 if (error) { 1592 mutex_exit(&cachep->c_contentslock); 1593 goto out; 1594 } 1595 mutex_exit(&cachep->c_contentslock); 1596 1597 /* copy out the new name */ 1598 if (rname) 1599 (void) strcpy(rname, namep); 1600 1601 out: 1602 /* clean up */ 1603 cachefs_cnode_stale(cp); 1604 1605 if (namebuf) 1606 cachefs_kmem_free(namebuf, MAXNAMELEN * 2); 1607 1608 #if 0 /* XXX until we can put filesystem in read-only mode */ 1609 if (error) { 1610 /* XXX put file system in read-only mode */ 1611 } 1612 #endif 1613 1614 return (error); 1615 } 1616 1617 /* 1618 * Traverses the list of cnodes on the fscache and calls the 1619 * specified routine with the held cnode. 1620 */ 1621 void 1622 cachefs_cnode_traverse(fscache_t *fscp, void (*routinep)(cnode_t *)) 1623 { 1624 filegrp_t *fgp, *ofgp; 1625 cnode_t *cp, *ocp; 1626 int index; 1627 1628 /* lock the fscache while we traverse the file groups */ 1629 mutex_enter(&fscp->fs_fslock); 1630 1631 /* for each bucket of file groups */ 1632 for (index = 0; index < CFS_FS_FGP_BUCKET_SIZE; index++) { 1633 ofgp = NULL; 1634 1635 /* for each file group in a bucket */ 1636 for (fgp = fscp->fs_filegrp[index]; 1637 fgp != NULL; 1638 fgp = fgp->fg_next) { 1639 1640 /* hold the file group */ 1641 filegrp_hold(fgp); 1642 1643 /* drop fscache lock so others can use it */ 1644 mutex_exit(&fscp->fs_fslock); 1645 1646 /* drop hold on previous file group */ 1647 if (ofgp) 1648 filegrp_rele(ofgp); 1649 ofgp = fgp; 1650 1651 /* lock the cnode list while we traverse it */ 1652 mutex_enter(&fgp->fg_cnodelock); 1653 ocp = NULL; 1654 1655 /* for each cnode in this file group */ 1656 for (cp = fgp->fg_cnodelist; 1657 cp != NULL; 1658 cp = cp->c_next) { 1659 1660 /* hold the cnode */ 1661 VN_HOLD(CTOV(cp)); 1662 1663 /* drop cnode list lock so others can use it */ 1664 mutex_exit(&fgp->fg_cnodelock); 1665 1666 /* drop hold on previous cnode */ 1667 if (ocp) { 1668 VN_RELE(CTOV(ocp)); 1669 } 1670 ocp = cp; 1671 1672 /* 1673 * Execute routine for this cnode. 1674 * At this point no locks are held. 1675 */ 1676 (routinep)(cp); 1677 1678 /* reaquire the cnode list lock */ 1679 mutex_enter(&fgp->fg_cnodelock); 1680 } 1681 1682 /* drop cnode list lock */ 1683 mutex_exit(&fgp->fg_cnodelock); 1684 1685 /* drop hold on last cnode */ 1686 if (ocp) { 1687 VN_RELE(CTOV(ocp)); 1688 } 1689 1690 /* reaquire the fscache lock */ 1691 mutex_enter(&fscp->fs_fslock); 1692 } 1693 1694 /* drop hold on last file group */ 1695 if (ofgp) 1696 filegrp_rele(ofgp); 1697 } 1698 mutex_exit(&fscp->fs_fslock); 1699 } 1700 1701 void 1702 cachefs_cnode_disable_caching(struct cnode *cp) 1703 { 1704 mutex_enter(&cp->c_statelock); 1705 cp->c_flags |= CN_NOCACHE; 1706 if (cp->c_frontvp != NULL) { 1707 VN_RELE(cp->c_frontvp); 1708 cp->c_frontvp = NULL; 1709 } 1710 mutex_exit(&cp->c_statelock); 1711 } 1712 1713 #define TIMEMATCH(a, b) ((a)->tv_sec == (b)->tv_sec && \ 1714 (a)->tv_nsec == (b)->tv_nsec) 1715 1716 static void 1717 cnode_enable_caching(struct cnode *cp) 1718 { 1719 struct vnode *iovp; 1720 struct filegrp *fgp; 1721 struct cachefs_metadata md; 1722 cachefscache_t *cachep = C_TO_FSCACHE(cp)->fs_cache; 1723 int error; 1724 1725 ASSERT((cachep->c_flags & (CACHE_NOFILL | CACHE_NOCACHE)) == 0); 1726 ASSERT(CFS_ISFS_BACKFS_NFSV4(C_TO_FSCACHE(cp)) == 0); 1727 1728 iovp = NULL; 1729 if (CTOV(cp)->v_type == VREG) 1730 iovp = cp->c_backvp; 1731 if (iovp) { 1732 (void) VOP_PUTPAGE(iovp, (offset_t)0, 1733 (uint_t)0, B_INVAL, kcred); 1734 } 1735 mutex_enter(&cp->c_statelock); 1736 if (cp->c_backvp) { 1737 VN_RELE(cp->c_backvp); 1738 cp->c_backvp = NULL; 1739 } 1740 fgp = cp->c_filegrp; 1741 ASSERT(fgp); 1742 error = filegrp_read_metadata(fgp, &cp->c_id, &md); 1743 if (error == 0) { 1744 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) && 1745 (md.md_rlno != 0) && 1746 (md.md_rltype == CACHEFS_RL_ACTIVE)) { 1747 rl_entry_t *rlp, rl; 1748 1749 mutex_enter(&cachep->c_contentslock); 1750 error = cachefs_rl_entry_get(cachep, md.md_rlno, &rlp); 1751 if (error) { 1752 mutex_exit(&cachep->c_contentslock); 1753 goto out; 1754 } 1755 1756 rl = *rlp; 1757 mutex_exit(&cachep->c_contentslock); 1758 1759 if (rl.rl_current != md.md_rltype) { 1760 md.md_rltype = rl.rl_current; 1761 cp->c_flags |= CN_UPDATED; 1762 } 1763 } 1764 1765 /* 1766 * A rudimentary consistency check 1767 * here. If the cookie and mtime 1768 * from the cnode match those from the 1769 * cache metadata, we assume for now that 1770 * the cached data is OK. 1771 */ 1772 if (bcmp(&md.md_cookie.fid_data, &cp->c_cookie.fid_data, 1773 (size_t)cp->c_cookie.fid_len) == 0 && 1774 TIMEMATCH(&cp->c_attr.va_mtime, &md.md_vattr.va_mtime)) { 1775 cp->c_metadata = md; 1776 } else { 1777 /* 1778 * Here we're skeptical about the validity of 1779 * the front file. 1780 * We'll keep the attributes already present in 1781 * the cnode, and bring along the parts of the 1782 * metadata that we need to eventually nuke this 1783 * bogus front file -- in inactive or getfrontfile, 1784 * whichever comes first... 1785 */ 1786 if (cp->c_frontvp != NULL) { 1787 VN_RELE(cp->c_frontvp); 1788 cp->c_frontvp = NULL; 1789 } 1790 cp->c_metadata.md_flags = md.md_flags; 1791 cp->c_metadata.md_flags |= MD_NEEDATTRS; 1792 cp->c_metadata.md_rlno = md.md_rlno; 1793 cp->c_metadata.md_rltype = md.md_rltype; 1794 cp->c_metadata.md_consttype = md.md_consttype; 1795 cp->c_metadata.md_fid = md.md_fid; 1796 cp->c_metadata.md_frontblks = md.md_frontblks; 1797 cp->c_metadata.md_timestamp.tv_sec = 0; 1798 cp->c_metadata.md_timestamp.tv_nsec = 0; 1799 bzero(&cp->c_metadata.md_allocinfo, 1800 cp->c_metadata.md_allocents * 1801 sizeof (struct cachefs_allocmap)); 1802 cp->c_metadata.md_allocents = 0; 1803 cp->c_metadata.md_flags &= ~MD_POPULATED; 1804 if ((cp->c_metadata.md_rlno != 0) && 1805 (cp->c_metadata.md_rltype == CACHEFS_RL_PACKED)) { 1806 cachefs_rlent_moveto(cachep, 1807 CACHEFS_RL_PACKED_PENDING, 1808 cp->c_metadata.md_rlno, 1809 cp->c_metadata.md_frontblks); 1810 cp->c_metadata.md_rltype = 1811 CACHEFS_RL_PACKED_PENDING; 1812 } 1813 1814 cp->c_flags |= CN_UPDATED; 1815 #ifdef CFSDEBUG 1816 CFS_DEBUG(CFSDEBUG_GENERAL) { 1817 printf( 1818 "fileno %lld ignores cached data due " 1819 "to cookie and/or mtime mismatch\n", 1820 (longlong_t)cp->c_id.cid_fileno); 1821 } 1822 #endif 1823 } 1824 if (cp->c_metadata.md_rltype == CACHEFS_RL_GC) { 1825 cachefs_rlent_moveto(cachep, CACHEFS_RL_ACTIVE, 1826 cp->c_metadata.md_rlno, 1827 cp->c_metadata.md_frontblks); 1828 cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE; 1829 cp->c_flags |= CN_UPDATED; 1830 } 1831 } 1832 1833 out: 1834 cp->c_flags &= ~CN_NOCACHE; 1835 mutex_exit(&cp->c_statelock); 1836 1837 (void) cachefs_pack_common(CTOV(cp), kcred); 1838 } 1839 1840 void 1841 cachefs_enable_caching(struct fscache *fscp) 1842 { 1843 1844 /* 1845 * This function is only called when a remount occurs, 1846 * with "nocache" and "nofill" options configured 1847 * (currently these aren't supported). Since this 1848 * function can write into the cache, make sure that 1849 * its not in use with NFSv4. 1850 */ 1851 if (CFS_ISFS_BACKFS_NFSV4(fscp)) 1852 return; 1853 1854 /* 1855 * set up file groups so we can read them. Note that general 1856 * users (makecfsnode) will *not* start using them (i.e., all 1857 * newly created cnodes will be NOCACHE) 1858 * until we "enable_caching_rw" below. 1859 */ 1860 mutex_enter(&fscp->fs_fslock); 1861 filegrp_list_enable_caching_ro(fscp); 1862 mutex_exit(&fscp->fs_fslock); 1863 1864 cachefs_cnode_traverse(fscp, cnode_enable_caching); 1865 1866 /* enable general use of the filegrps */ 1867 mutex_enter(&fscp->fs_fslock); 1868 filegrp_list_enable_caching_rw(fscp); 1869 mutex_exit(&fscp->fs_fslock); 1870 } 1871 1872 /* 1873 * This function makes a cnode stale by performing the following tasks: 1874 * 1) remove the front file 1875 * 2) Remove any resource file entries 1876 * 3) Remove any metadata entry from the attrcache file 1877 * 4) Set the stale bit in the cnode flags field 1878 */ 1879 void 1880 cachefs_cnode_stale(cnode_t *cp) 1881 { 1882 fscache_t *fscp = C_TO_FSCACHE(cp); 1883 struct cachefs_metadata *mdp; 1884 1885 ASSERT(MUTEX_HELD(&cp->c_statelock)); 1886 1887 /* 1888 * Remove a metadata entry if the file exists 1889 */ 1890 mdp = &cp->c_metadata; 1891 if (mdp->md_rlno) { 1892 1893 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0); 1894 1895 /* 1896 * destroy the frontfile 1897 */ 1898 cachefs_removefrontfile(mdp, &cp->c_id, cp->c_filegrp); 1899 /* 1900 * Remove resource file entry 1901 */ 1902 cachefs_rlent_moveto(fscp->fs_cache, CACHEFS_RL_FREE, 1903 mdp->md_rlno, 0); 1904 mdp->md_rlno = 0; 1905 mdp->md_rltype = CACHEFS_RL_NONE; 1906 } 1907 1908 /* 1909 * Remove attrcache metadata 1910 */ 1911 if (CFS_ISFS_BACKFS_NFSV4(fscp) == 0) 1912 (void) filegrp_destroy_metadata(cp->c_filegrp, &cp->c_id); 1913 mdp->md_flags = 0; 1914 1915 if (cp->c_frontvp) { 1916 VN_RELE(cp->c_frontvp); 1917 cp->c_frontvp = NULL; 1918 } 1919 1920 /* 1921 * For NFSv4 need to hang on to the backvp until vn_rele() 1922 * frees this cnode. 1923 */ 1924 if (cp->c_backvp && !CFS_ISFS_BACKFS_NFSV4(fscp)) { 1925 VN_RELE(cp->c_backvp); 1926 cp->c_backvp = NULL; 1927 } 1928 if (cp->c_acldirvp) { 1929 VN_RELE(cp->c_acldirvp); 1930 cp->c_acldirvp = NULL; 1931 } 1932 1933 cp->c_flags |= CN_STALE | CN_ALLOC_PENDING | CN_NOCACHE; 1934 } 1935 1936 /* 1937 * Sets up the local attributes in the metadata from the attributes. 1938 */ 1939 void 1940 cachefs_cnode_setlocalstats(cnode_t *cp) 1941 { 1942 fscache_t *fscp = C_TO_FSCACHE(cp); 1943 cachefs_metadata_t *mdp = &cp->c_metadata; 1944 1945 ASSERT(MUTEX_HELD(&cp->c_statelock)); 1946 1947 /* allow over writing of local attributes if a remount occurred */ 1948 if (fscp->fs_info.fi_resettimes != mdp->md_resettimes) { 1949 mdp->md_flags &= ~(MD_LOCALCTIME | MD_LOCALMTIME); 1950 mdp->md_resettimes = fscp->fs_info.fi_resettimes; 1951 } 1952 if (fscp->fs_info.fi_resetfileno != mdp->md_resetfileno) { 1953 mdp->md_flags &= ~MD_LOCALFILENO; 1954 mdp->md_resetfileno = fscp->fs_info.fi_resetfileno; 1955 } 1956 1957 /* overwrite old fileno and timestamps if not local versions */ 1958 if ((mdp->md_flags & MD_LOCALFILENO) == 0) 1959 mdp->md_localfileno = mdp->md_vattr.va_nodeid; 1960 if ((mdp->md_flags & MD_LOCALCTIME) == 0) 1961 mdp->md_localctime = mdp->md_vattr.va_ctime; 1962 if ((mdp->md_flags & MD_LOCALMTIME) == 0) 1963 mdp->md_localmtime = mdp->md_vattr.va_mtime; 1964 cp->c_flags |= CN_UPDATED; 1965 } 1966