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 
  29 #include <sys/param.h>
  30 #include <sys/types.h>
  31 #include <sys/systm.h>
  32 #include <sys/cred.h>
  33 #include <sys/proc.h>
  34 #include <sys/user.h>
  35 #include <sys/vfs.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/buf.h>
  43 #include <netinet/in.h>
  44 #include <rpc/types.h>
  45 #include <rpc/xdr.h>
  46 #include <rpc/auth.h>
  47 #include <rpc/clnt.h>
  48 #include <sys/mount.h>
  49 #include <sys/ioctl.h>
  50 #include <sys/statvfs.h>
  51 #include <sys/errno.h>
  52 #include <sys/debug.h>
  53 #include <sys/cmn_err.h>
  54 #include <sys/utsname.h>
  55 #include <sys/modctl.h>
  56 #include <vm/pvn.h>
  57 
  58 #include <sys/fs/cachefs_fs.h>
  59 
  60 /*
  61  * cachefs_max_idle is a global that is tunable.
  62  * This value decides how frequently or when the
  63  * cachefs_cnode_idleclean is run.
  64  * The default value is set to CFS_FS_MAXIDLE.
  65  * The tunable if set to X triggers a cleanup when
  66  * the number of idle cnodes reach X, and cleans up
  67  * (.25 * X) idle cnodes.
  68  */
  69 int cachefs_max_idle = CFS_FS_MAXIDLE;
  70 
  71 
  72 struct kmem_cache *cachefs_cnode_cache = NULL;
  73 
  74 /*
  75  * Functions for cnode management.
  76  */
  77 
  78 /*
  79  * Puts cnode on idle list.  Only call from an async thread or no
  80  * locks held.
  81  */
  82 /*ARGSUSED1*/
  83 void
  84 cachefs_cnode_idle(struct vnode *vp, cred_t *cr)
  85 {
  86         cnode_t *cp = VTOC(vp);
  87         fscache_t *fscp = C_TO_FSCACHE(cp);
  88         int cleanidle;
  89         vnode_t *unldvp;
  90         cred_t *unlcred;
  91         char *unlname;
  92         int error;
  93 
  94         /*
  95          * The key to this routine is not to drop the vnode count
  96          * while on the idle list.  This prevents this routine from
  97          * being called again by vn_rele on an inactive cnode.
  98          * Nothing bad happens if an "active" cnode is put on the idle
  99          * list.  It eventually gets pulled off.
 100          * Also this routine is only called from a thread message sent
 101          * by cachefs_inactive().  It is not safe for this routine
 102          * to be the "inactive" entry point because of the dnlc.
 103          */
 104 
 105         for (;;) {
 106                 /* get access to the file system */
 107                 error = cachefs_cd_access(fscp, 0, 1);
 108                 ASSERT(error == 0);
 109 
 110                 /* get exclusive access to this cnode */
 111                 mutex_enter(&cp->c_statelock);
 112 
 113                 /* done with this loop if not unlinking a file */
 114                 if (cp->c_unldvp == NULL)
 115                         break;
 116 
 117                 /* get unlink info out of the cnode */
 118                 unldvp = cp->c_unldvp;
 119                 unlcred = cp->c_unlcred;
 120                 unlname = cp->c_unlname;
 121                 cp->c_unldvp = NULL;
 122                 cp->c_unlcred = NULL;
 123                 cp->c_unlname = NULL;
 124                 mutex_exit(&cp->c_statelock);
 125 
 126                 /* finish the remove operation */
 127                 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
 128                         error = cachefs_remove_connected(unldvp,
 129                             unlname, unlcred, vp);
 130                 } else {
 131                         error = cachefs_remove_disconnected(unldvp,
 132                             unlname, unlcred, vp);
 133                 }
 134 
 135                 /* reacquire cnode lock */
 136                 mutex_enter(&cp->c_statelock);
 137 
 138                 /* if a timeout occurred */
 139                 if (CFS_TIMEOUT(fscp, error)) {
 140                         /* restore cnode state */
 141                         if (cp->c_unldvp == NULL) {
 142                                 cp->c_unldvp = unldvp;
 143                                 cp->c_unlcred = unlcred;
 144                                 cp->c_unlname = unlname;
 145                                 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
 146                                         mutex_exit(&cp->c_statelock);
 147                                         cachefs_cd_release(fscp);
 148                                         cachefs_cd_timedout(fscp);
 149                                         continue;
 150                                 } else {
 151                                         cp->c_flags |= CN_PENDRM;
 152                                         mutex_exit(&cp->c_statelock);
 153                                         goto out;
 154                                 }
 155                         }
 156                 }
 157                 /* free up resources */
 158                 VN_RELE(unldvp);
 159                 cachefs_kmem_free(unlname, MAXNAMELEN);
 160                 crfree(unlcred);
 161                 break;
 162         }
 163 
 164         ASSERT((cp->c_flags & CN_IDLE) == 0);
 165         /*
 166          * If we are going to destroy this cnode,
 167          * do it now instead of later.
 168          */
 169         if (cp->c_flags & (CN_DESTROY | CN_STALE)) {
 170                 mutex_exit(&cp->c_statelock);
 171                 (void) cachefs_cnode_inactive(vp, cr);
 172                 goto out;
 173         }
 174 
 175         /*
 176          * mark cnode as idle, put it on the idle list, and increment the
 177          * number of idle cnodes
 178          */
 179         cp->c_flags |= CN_IDLE;
 180         mutex_enter(&fscp->fs_idlelock);
 181         cachefs_cnode_idleadd(cp);
 182         if ((fscp->fs_idlecnt > cachefs_max_idle) &&
 183             (fscp->fs_idleclean == 0) &&
 184             (fscp->fs_cdtransition == 0)) {
 185                 fscp->fs_idleclean = 1;
 186                 cleanidle = 1;
 187         } else {
 188                 cleanidle = 0;
 189         }
 190         mutex_exit(&fscp->fs_idlelock);
 191 
 192         /* release cnode */
 193         mutex_exit(&cp->c_statelock);
 194 
 195         /* if should reduce the number of idle cnodes */
 196         if (cleanidle) {
 197                 ASSERT(fscp->fs_idlecnt > 1);
 198                 fscache_hold(fscp);
 199                 cachefs_cnode_idleclean(fscp, 0);
 200                 /* XXX race with cachefs_unmount() calling destroy */
 201                 fscache_rele(fscp);
 202         }
 203 
 204 out:
 205         /* release hold on the file system */
 206         /* XXX unmount() could have called destroy after fscache_rele() */
 207         cachefs_cd_release(fscp);
 208 }
 209 
 210 /*
 211  * Removes cnodes from the idle list and destroys them.
 212  */
 213 void
 214 cachefs_cnode_idleclean(fscache_t *fscp, int unmount)
 215 {
 216         int remcnt;
 217         cnode_t *cp;
 218 
 219         mutex_enter(&fscp->fs_idlelock);
 220 
 221         /* determine number of cnodes to destroy */
 222         if (unmount) {
 223                 /* destroy all plus any that go idle while in this routine */
 224                 remcnt = fscp->fs_idlecnt * 2;
 225         } else {
 226                 /* reduce to 75% of max allowed idle cnodes */
 227                 remcnt = (fscp->fs_idlecnt - cachefs_max_idle) +
 228                     (cachefs_max_idle >> 2);
 229         }
 230 
 231         for (; remcnt > 0; remcnt--) {
 232                 /* get cnode on back of idle list and hold it */
 233                 cp = fscp->fs_idleback;
 234                 if (cp == NULL)
 235                         break;
 236                 VN_HOLD(CTOV(cp));
 237                 mutex_exit(&fscp->fs_idlelock);
 238 
 239                 /* if the cnode is still on the idle list */
 240                 mutex_enter(&cp->c_statelock);
 241                 if (cp->c_flags & CN_IDLE) {
 242                         cp->c_flags &= ~CN_IDLE;
 243 
 244                         /* remove cnode from the idle list */
 245                         mutex_enter(&fscp->fs_idlelock);
 246                         cachefs_cnode_idlerem(cp);
 247                         mutex_exit(&fscp->fs_idlelock);
 248                         mutex_exit(&cp->c_statelock);
 249 
 250                         /* destroy the cnode */
 251                         VN_RELE(CTOV(cp));
 252                         (void) cachefs_cnode_inactive(CTOV(cp), kcred);
 253                 } else {
 254                         /* cnode went active, just skip it */
 255                         mutex_exit(&cp->c_statelock);
 256                         VN_RELE(CTOV(cp));
 257                 }
 258                 mutex_enter(&fscp->fs_idlelock);
 259         }
 260 
 261         fscp->fs_idleclean = 0;
 262         mutex_exit(&fscp->fs_idlelock);
 263 }
 264 
 265 /*
 266  * This routine does the real work of inactivating a cachefs vnode.
 267  */
 268 int
 269 cachefs_cnode_inactive(register struct vnode *vp, cred_t *cr)
 270 {
 271         cnode_t *cp;
 272         struct fscache *fscp;
 273         struct filegrp *fgp;
 274         cachefscache_t *cachep;
 275         struct cachefs_metadata *mdp;
 276         int meta_destroyed = 0;
 277 
 278         cp = VTOC(vp);
 279 
 280         fscp = C_TO_FSCACHE(cp);
 281         cachep = fscp->fs_cache;
 282         ASSERT(cachep != NULL);
 283         fgp = cp->c_filegrp;
 284 
 285         ASSERT((cp->c_flags & CN_IDLE) == 0);
 286 
 287         /* truncate the front file if necessary */
 288         mutex_enter(&cp->c_statelock);
 289         if ((cp->c_flags & CN_NOCACHE) && (cp->c_metadata.md_flags & MD_FILE) &&
 290             cp->c_metadata.md_frontblks) {
 291 
 292                 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
 293 
 294 #ifdef CFSDEBUG
 295                 CFS_DEBUG(CFSDEBUG_INVALIDATE)
 296                         printf("c_cnode_inactive: invalidating %llu\n",
 297                             (u_longlong_t)cp->c_id.cid_fileno);
 298 #endif
 299                 /*
 300                  * If the cnode is being populated, and we're not the
 301                  * populating thread, then block until the pop thread
 302                  * completes.  If we are the pop thread, then we may come in
 303                  * here, but not to nuke the directory cnode at a critical
 304                  * juncture.
 305                  */
 306                 while ((cp->c_flags & CN_ASYNC_POP_WORKING) &&
 307                     (cp->c_popthrp != curthread))
 308                         cv_wait(&cp->c_popcv, &cp->c_statelock);
 309 
 310                 cachefs_inval_object(cp);
 311         }
 312         mutex_exit(&cp->c_statelock);
 313 
 314         for (;;) {
 315                 /* see if vnode is really inactive */
 316                 mutex_enter(&vp->v_lock);
 317                 ASSERT(vp->v_count > 0);
 318                 if (vp->v_count > 1) {
 319                         /*
 320                          * It's impossible for us to be cnode_inactive for
 321                          * the root cnode _unless_ we are being called from
 322                          * cachefs_unmount (where inactive is called
 323                          * explictly).  If the count is not 1, there is
 324                          * still an outstanding reference to the root cnode,
 325                          * and we return EBUSY; this allows cachefs_unmount
 326                          * to fail.
 327                          */
 328                         if (cp->c_flags & CN_ROOT) {
 329                                 mutex_exit(&vp->v_lock);
 330                                 return (EBUSY);
 331                         }
 332                         cp->c_ipending = 0;
 333                         vp->v_count--;       /* release our hold from vn_rele */
 334                         mutex_exit(&vp->v_lock);
 335                         return (0);
 336                 }
 337                 mutex_exit(&vp->v_lock);
 338 
 339                 /* get rid of any pages, do not care if cannot be pushed */
 340                 if (vn_has_cached_data(vp)) {
 341                         ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
 342                         (void) cachefs_putpage_common(vp, (offset_t)0, 0,
 343                             B_INVAL | B_FORCE, cr);
 344                 }
 345 
 346                 /* if need to sync metadata, the call is a no op for NFSv4 */
 347                 if ((cp->c_flags & (CN_UPDATED | CN_DESTROY)) == CN_UPDATED) {
 348                         (void) cachefs_sync_metadata(cp);
 349                         continue;
 350                 }
 351                 break;
 352         }
 353 
 354         /*
 355          * Lock out possible race with makecachefsnode.
 356          * Makecachefsnode will fix up the rl/active list stuff to
 357          * be correct when it gets to run.
 358          * We have to do the rl/active stuff while the cnode is on the hash
 359          * list to sync actions on the rl/active list.
 360          */
 361         mutex_enter(&fgp->fg_cnodelock);
 362         mutex_enter(&cp->c_statelock);
 363 
 364         /* see if vnode is still inactive */
 365         mutex_enter(&vp->v_lock);
 366         ASSERT(vp->v_count > 0);
 367         if (vp->v_count > 1) {
 368                 cp->c_ipending = 0;
 369                 vp->v_count--;
 370                 mutex_exit(&vp->v_lock);
 371                 mutex_exit(&cp->c_statelock);
 372                 mutex_exit(&fgp->fg_cnodelock);
 373 #ifdef CFSDEBUG
 374                 CFS_DEBUG(CFSDEBUG_INVALIDATE)
 375                         printf("cachefs_cnode_inactive: %u vp %p\n",
 376                             vp->v_count, vp);
 377 #endif
 378                 return (0);
 379         }
 380         mutex_exit(&vp->v_lock);
 381 
 382         /* check for race with remove */
 383         if (cp->c_unldvp) {
 384                 mutex_exit(&cp->c_statelock);
 385                 mutex_exit(&fgp->fg_cnodelock);
 386 
 387                 /* this causes cachefs_inactive to be called again */
 388                 VN_RELE(vp);
 389                 return (0);
 390         }
 391 
 392         /* if any pages left, really get rid of them */
 393         if (vn_has_cached_data(vp)) {
 394                 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
 395                 (void) pvn_vplist_dirty(vp, 0, NULL, B_INVAL | B_TRUNC, cr);
 396         }
 397         ASSERT(vp->v_count == 1);
 398 
 399         mdp = &cp->c_metadata;
 400 
 401         /* if we can (and should) destroy the front file and metadata */
 402         if ((cp->c_flags & (CN_DESTROY | CN_STALE)) &&
 403             (fgp->fg_flags & CFS_FG_WRITE) && !CFS_ISFS_BACKFS_NFSV4(fscp)) {
 404                 if (mdp->md_rlno) {
 405                         cachefs_removefrontfile(mdp, &cp->c_id, fgp);
 406                         cachefs_rlent_moveto(cachep, CACHEFS_RL_FREE,
 407                             mdp->md_rlno, 0);
 408                         mdp->md_rlno = 0;
 409                         mdp->md_rltype = CACHEFS_RL_NONE;
 410                 }
 411                 if ((cp->c_flags & CN_ALLOC_PENDING) == 0) {
 412                         (void) filegrp_destroy_metadata(fgp, &cp->c_id);
 413                         meta_destroyed = 1;
 414                 }
 415         }
 416 
 417         /* else put the front file on the gc list */
 418         else if (mdp->md_rlno &&
 419             (fgp->fg_flags & CFS_FG_WRITE) &&
 420             (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) {
 421 #ifdef CFSDEBUG
 422                 cachefs_rlent_verify(cachep, CACHEFS_RL_ACTIVE,
 423                     mdp->md_rlno);
 424 #endif /* CFSDEBUG */
 425 
 426                 ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
 427                 cachefs_rlent_moveto(cachep, CACHEFS_RL_GC, mdp->md_rlno,
 428                     mdp->md_frontblks);
 429                 mdp->md_rltype = CACHEFS_RL_GC;
 430                 cp->c_flags |= CN_UPDATED;
 431         }
 432 
 433         /* if idlelist pointer(s) not null, remove from idle list */
 434         if ((cp->c_idlefront != NULL) || (cp->c_idleback != NULL)) {
 435                 mutex_enter(&fscp->fs_idlelock);
 436                 cachefs_cnode_idlerem(cp);
 437                 mutex_exit(&fscp->fs_idlelock);
 438         }
 439 
 440         /* remove from the filegrp list prior to releasing the cnode lock */
 441         cachefs_cnode_listrem(cp);
 442 
 443         mutex_exit(&cp->c_statelock);
 444         if (! meta_destroyed)
 445                 (void) cachefs_sync_metadata(cp);
 446 
 447         mutex_exit(&fgp->fg_cnodelock);
 448 
 449         if (cp->c_cred != NULL) {
 450                 crfree(cp->c_cred);
 451                 cp->c_cred = NULL;
 452         }
 453 
 454         if (cp->c_frontvp)
 455                 VN_RELE(cp->c_frontvp);
 456 
 457         if (cp->c_backvp)
 458                 VN_RELE(cp->c_backvp);
 459 
 460         if (cp->c_acldirvp)
 461                 VN_RELE(cp->c_acldirvp);
 462 
 463         rw_destroy(&cp->c_rwlock);
 464         mutex_destroy(&cp->c_statelock);
 465         cv_destroy(&cp->c_popcv);
 466         mutex_destroy(&cp->c_iomutex);
 467         cv_destroy(&cp->c_iocv);
 468 
 469         /* free up cnode memory */
 470         vn_invalid(cp->c_vnode);
 471         vn_free(cp->c_vnode);
 472         kmem_cache_free(cachefs_cnode_cache, cp);
 473 
 474         filegrp_rele(fgp);
 475         (void) fscache_cnodecnt(fscp, -1);
 476         return (0);
 477 }
 478 
 479 /*
 480  * Add a cnode to the filegrp list.
 481  */
 482 void
 483 cachefs_cnode_listadd(struct cnode *cp)
 484 {
 485         filegrp_t *fgp = cp->c_filegrp;
 486 
 487         ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
 488         ASSERT(cp->c_next == NULL);
 489 
 490         cp->c_next = fgp->fg_cnodelist;
 491         fgp->fg_cnodelist = cp;
 492 }
 493 
 494 /*
 495  * Remove a cnode from the filegrp list.
 496  */
 497 void
 498 cachefs_cnode_listrem(struct cnode *cp)
 499 {
 500         filegrp_t *fgp = cp->c_filegrp;
 501         struct cnode **headpp;
 502 
 503 #ifdef CFSDEBUG
 504         int found = 0;
 505 #endif
 506 
 507         ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
 508         ASSERT(cp->c_idleback == NULL);
 509         ASSERT(cp->c_idlefront == NULL);
 510 
 511         for (headpp = &fgp->fg_cnodelist;
 512                 *headpp != NULL; headpp = &(*headpp)->c_next) {
 513                 if (*headpp == cp) {
 514                         *headpp = cp->c_next;
 515                         cp->c_next = NULL;
 516 #ifdef CFSDEBUG
 517                         found++;
 518 #endif
 519                         break;
 520                 }
 521         }
 522 #ifdef CFSDEBUG
 523         ASSERT(found);
 524 #endif
 525 }
 526 
 527 /*
 528  * Add a cnode to the front of the fscache idle list.
 529  */
 530 void
 531 cachefs_cnode_idleadd(struct cnode *cp)
 532 {
 533         fscache_t *fscp = C_TO_FSCACHE(cp);
 534 
 535         ASSERT(MUTEX_HELD(&cp->c_statelock));
 536         ASSERT(MUTEX_HELD(&fscp->fs_idlelock));
 537 
 538         /* put cnode on the front of the idle list */
 539         cp->c_idlefront = fscp->fs_idlefront;
 540         cp->c_idleback =  NULL;
 541 
 542         if (fscp->fs_idlefront)
 543                 fscp->fs_idlefront->c_idleback = cp;
 544         else {
 545                 ASSERT(fscp->fs_idleback == NULL);
 546                 fscp->fs_idleback = cp;
 547         }
 548         fscp->fs_idlefront = cp;
 549         fscp->fs_idlecnt++;
 550 }
 551 
 552 /*
 553  * Remove a cnode from the fscache idle list.
 554  */
 555 void
 556 cachefs_cnode_idlerem(struct cnode *cp)
 557 {
 558         fscache_t *fscp = C_TO_FSCACHE(cp);
 559 
 560         ASSERT(MUTEX_HELD(&cp->c_statelock));
 561         ASSERT(MUTEX_HELD(&fscp->fs_idlelock));
 562 
 563         if (cp->c_idlefront == NULL) {
 564                 ASSERT(fscp->fs_idleback == cp);
 565                 fscp->fs_idleback = cp->c_idleback;
 566                 if (fscp->fs_idleback != NULL)
 567                         fscp->fs_idleback->c_idlefront = NULL;
 568         } else {
 569                 cp->c_idlefront->c_idleback = cp->c_idleback;
 570         }
 571 
 572         if (cp->c_idleback == NULL) {
 573                 ASSERT(fscp->fs_idlefront == cp);
 574                 fscp->fs_idlefront = cp->c_idlefront;
 575                 if (fscp->fs_idlefront != NULL)
 576                         fscp->fs_idlefront->c_idleback = NULL;
 577         } else {
 578                 cp->c_idleback->c_idlefront = cp->c_idlefront;
 579                 cp->c_idleback = NULL;
 580         }
 581         cp->c_idlefront = NULL;
 582         fscp->fs_idlecnt--;
 583         ASSERT(fscp->fs_idlecnt >= 0);
 584 }
 585 
 586 /*
 587  * Search the cnode list of the input file group, looking for a cnode which
 588  * matches the supplied file ident fileno.
 589  *
 590  * Returns:
 591  *      *cpp = NULL, if no valid matching cnode is found
 592  *      *cpp = address of cnode with matching fileno, with c_statelock held
 593  *      return status is 0 if no cnode found, or if found & cookies match
 594  *      return status is 1 if a cnode was found, but the cookies don't match
 595  *
 596  * Note:  must grab the c_statelock for each cnode, or its state could
 597  * change while we're processing it.  Also, if a cnode is found, must return
 598  * with c_statelock still held, so that the cnode state cannot change until
 599  * the calling routine releases the lock.
 600  */
 601 int
 602 cachefs_cnode_find(filegrp_t *fgp, cfs_cid_t *cidp, fid_t *cookiep,
 603     struct cnode **cpp, struct vnode *backvp, vattr_t *vap)
 604 {
 605         struct cnode *cp;
 606         int badcookie = 0;
 607         uint32_t is_nfsv4;
 608 
 609 #ifdef CFSDEBUG
 610         CFS_DEBUG(CFSDEBUG_CNODE)
 611                 cmn_err(CE_NOTE, "cachefs_cnode_find: fileno %llu fgp %p\n",
 612                     (u_longlong_t)cidp->cid_fileno, (void *)fgp);
 613 #endif
 614         ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
 615 
 616         *cpp = NULL;
 617         is_nfsv4 = CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp);
 618 
 619         /*
 620          * Cookie should be filled unless disconnected operation or
 621          * backfilesystem is NFSv4
 622          */
 623         if (cookiep == NULL && !CFS_ISFS_SNR(fgp->fg_fscp) &&
 624             !CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) {
 625                 goto out;
 626         }
 627 
 628         for (cp = fgp->fg_cnodelist; cp != NULL; cp = cp->c_next) {
 629                 mutex_enter(&cp->c_statelock);
 630 
 631                 if ((cidp->cid_fileno != cp->c_id.cid_fileno &&
 632                         (is_nfsv4 == FALSE || cp->c_backvp != backvp)) ||
 633                     (cp->c_flags & (CN_STALE | CN_DESTROY))) {
 634                         mutex_exit(&cp->c_statelock);
 635                         continue;
 636                 }
 637 
 638                 /*
 639                  * Having found a non stale, non destroy pending cnode with
 640                  * matching fileno, will be exiting the for loop, after
 641                  * determining return status
 642                  */
 643                 *cpp = cp;
 644 
 645                 if ((cookiep != NULL) &&
 646                     ((cookiep->fid_len != cp->c_cookie.fid_len) ||
 647                     (bcmp((caddr_t)cookiep->fid_data,
 648                     (caddr_t)&cp->c_cookie.fid_data, cookiep->fid_len)) != 0)) {
 649 #ifdef CFSDEBUG
 650                         CFS_DEBUG(CFSDEBUG_GENERAL) {
 651                                 cmn_err(CE_NOTE,
 652                                     "cachefs: dup fileno %llu, cp %p\n",
 653                                     (u_longlong_t)cidp->cid_fileno, (void *)cp);
 654                         }
 655 #endif
 656                         badcookie = 1;
 657                 }
 658 
 659                 /*
 660                  * For NFSv4 since there is no fid, add a check to
 661                  * ensure the backvp and vap matches that in the cnode.
 662                  * If it doesn't then someone tried to use a stale cnode.
 663                  */
 664                 if (is_nfsv4) {
 665                         if (backvp && backvp != cp->c_backvp ||
 666                             vap && vap->va_type != cp->c_attr.va_type ||
 667                             cidp->cid_fileno != cp->c_id.cid_fileno) {
 668                                 CFS_DPRINT_BACKFS_NFSV4(C_TO_FSCACHE(cp),
 669                                 ("cachefs_cnode_find (nfsv4): stale cnode "
 670                                 "cnode %p, backvp %p, new-backvp %p, vap %p "
 671                                 "fileno=%llx cp-fileno=%llx\n",
 672                                 cp, cp->c_backvp, backvp, vap,
 673                                 cidp->cid_fileno, cp->c_id.cid_fileno));
 674                                 badcookie = 1;
 675                         }
 676                 }
 677                 break;
 678         }
 679 out:
 680 
 681 #ifdef CFSDEBUG
 682         CFS_DEBUG(CFSDEBUG_CNODE)
 683                 cmn_err(CE_NOTE, "cachefs_cnode_find: cp %p\n", (void *)*cpp);
 684 #endif
 685         return (badcookie);
 686 }
 687 
 688 /*
 689  * We have to initialize the cnode contents. Fill in the contents from the
 690  * cache (attrcache file), from the info passed in, whatever it takes.
 691  */
 692 static int
 693 cachefs_cnode_init(cfs_cid_t *cidp, cnode_t *cp, fscache_t *fscp,
 694     filegrp_t *fgp, fid_t *cookiep, vattr_t *vap, vnode_t *backvp,
 695     int flag, cred_t *cr)
 696 {
 697         int error = 0;
 698         int slotfound;
 699         vnode_t *vp;
 700         int null_cookie;
 701         cachefscache_t *cachep = fscp->fs_cache;
 702 
 703         bzero(cp, sizeof (cnode_t));
 704         cp->c_vnode = vn_alloc(KM_SLEEP);
 705 
 706         vp = CTOV(cp);
 707 
 708         vp->v_data = (caddr_t)cp;
 709 
 710         rw_init(&cp->c_rwlock, NULL, RW_DEFAULT, NULL);
 711         mutex_init(&cp->c_statelock, NULL, MUTEX_DEFAULT, NULL);
 712         cv_init(&cp->c_popcv, NULL, CV_DEFAULT, NULL);
 713         mutex_init(&cp->c_iomutex, NULL, MUTEX_DEFAULT, NULL);
 714         cv_init(&cp->c_iocv, NULL, CV_DEFAULT, NULL);
 715 
 716         vn_setops(vp, cachefs_getvnodeops());
 717         cp->c_id = *cidp;
 718         if (backvp != NULL) {
 719                 cp->c_backvp = backvp;
 720                 VN_HOLD(backvp);
 721         }
 722         cp->c_flags |= flag;
 723         filegrp_hold(fgp);
 724         cp->c_filegrp = fgp;
 725         if (cookiep)
 726                 cp->c_cookie = *cookiep;
 727         mutex_enter(&cp->c_statelock);
 728 
 729         /*
 730          * if nocache is set then ignore anything cached for this file,
 731          * if nfsv4 flag is set, then create the cnode but don't do
 732          * any caching.
 733          */
 734         if (cp->c_flags & CN_NOCACHE || CFS_ISFS_BACKFS_NFSV4(fscp)) {
 735                 /*
 736                  * this case only happens while booting without a cache
 737                  * or if NFSv4 is the backfilesystem
 738                  */
 739                 ASSERT(!CFS_ISFS_SNR(fscp));
 740                 ASSERT(fscp->fs_cdconnected == CFS_CD_CONNECTED);
 741                 if (cookiep || CFS_ISFS_BACKFS_NFSV4(fscp)) {
 742                         error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
 743                         if (error)
 744                                 goto out;
 745                         cp->c_flags |= CN_UPDATED | CN_ALLOC_PENDING;
 746                         ASSERT(cp->c_attr.va_type != 0);
 747                         VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
 748                             cp->c_attr.va_type, cp->c_attr.va_rdev);
 749                         cachefs_cnode_setlocalstats(cp);
 750                 } else
 751                         error = ESTALE;
 752                 goto out;
 753         }
 754 
 755         /*
 756          * see if there's a slot for this filegrp/cid fileno
 757          * if not, and there's no cookie info, nothing can be done, but if
 758          * there's cookie data indicate we need to create a metadata slot.
 759          */
 760         slotfound = cachefs_cid_inuse(cp->c_filegrp, cidp);
 761         if (slotfound == 0) {
 762                 if (cookiep == NULL) {
 763                         error = ENOENT;
 764                         goto out;
 765                 }
 766                 cp->c_flags |= CN_ALLOC_PENDING;
 767         } else {
 768                 /*
 769                  * if a slot was found, then increment the slot in use count
 770                  * and try to read the metadata.
 771                  */
 772                 cp->c_filegrp->fg_header->ach_count++;
 773                 error = filegrp_read_metadata(cp->c_filegrp, cidp,
 774                     &cp->c_metadata);
 775         }
 776         /*
 777          * if there wasn't a slot, or an attempt to read it results in ENOENT,
 778          * then init the cache object, create the vnode, etc...
 779          */
 780         if ((slotfound == 0) || (error == ENOENT)) {
 781                 error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
 782                 if (error)
 783                         goto out;
 784                 ASSERT(cp->c_attr.va_type != 0);
 785                 VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
 786                     cp->c_attr.va_type, cp->c_attr.va_rdev);
 787                 cp->c_metadata.md_rltype = CACHEFS_RL_NONE;
 788         } else if (error == 0) {
 789                 /* slot found, no error occurred on the metadata read */
 790                 cp->c_size = cp->c_attr.va_size;
 791 
 792                 if ((cachep->c_flags & CACHE_CHECK_RLTYPE) &&
 793                     (cp->c_metadata.md_rlno != 0) &&
 794                     (cp->c_metadata.md_rltype == CACHEFS_RL_ACTIVE)) {
 795                         rl_entry_t rl, *rlp;
 796 
 797                         mutex_enter(&cachep->c_contentslock);
 798                         error = cachefs_rl_entry_get(cachep,
 799                             cp->c_metadata.md_rlno, &rlp);
 800                         if (error) {
 801                                 mutex_exit(&cachep->c_contentslock);
 802                                 goto out;
 803                         }
 804                         rl = *rlp;
 805                         mutex_exit(&cachep->c_contentslock);
 806                         if (cp->c_metadata.md_rltype != rl.rl_current) {
 807                                 cp->c_flags |= CN_UPDATED;
 808                                 cp->c_metadata.md_rltype = rl.rl_current;
 809                         }
 810                 }
 811 
 812                 /*
 813                  * If no cookie is specified, or if this is a local file,
 814                  * accept the one in the metadata.
 815                  */
 816                 null_cookie = 0;
 817                 if ((cookiep == NULL) || (cp->c_id.cid_flags & CFS_CID_LOCAL)) {
 818                         cookiep = &cp->c_metadata.md_cookie;
 819                         null_cookie = 1;
 820                 }
 821 
 822                 /* if cookies do not match, reset the metadata */
 823                 if ((cookiep->fid_len != cp->c_cookie.fid_len) ||
 824                     (bcmp(&cookiep->fid_data, &cp->c_cookie.fid_data,
 825                         (size_t)cookiep->fid_len) != 0)) {
 826                         cp->c_cookie = *cookiep;
 827                         cp->c_flags |= CN_UPDATED;
 828                         cp->c_metadata.md_timestamp.tv_sec = 0;
 829                         /* clear all but the front file bit */
 830                         cp->c_metadata.md_flags &= MD_FILE;
 831                         error = CFSOP_INIT_COBJECT(fscp, cp, vap, cr);
 832                         ASSERT(cp->c_attr.va_type != 0);
 833                         VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
 834                             cp->c_attr.va_type, cp->c_attr.va_rdev);
 835                 }
 836 
 837                 /* else if the consistency type changed, fix it up */
 838                 else if (cp->c_metadata.md_consttype != fscp->fs_consttype) {
 839                         ASSERT(cp->c_attr.va_type != 0);
 840                         VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
 841                             cp->c_attr.va_type, cp->c_attr.va_rdev);
 842                         CFSOP_CONVERT_COBJECT(fscp, cp, cr);
 843                         if (!null_cookie) {
 844                                 error = CFSOP_CHECK_COBJECT(fscp, cp,
 845                                     C_BACK_CHECK, cr);
 846                         }
 847                 }
 848 
 849                 /* else check the consistency of the data */
 850                 else {
 851                         ASSERT(cp->c_attr.va_type != 0);
 852                         VN_SET_VFS_TYPE_DEV(vp, fscp->fs_cfsvfsp,
 853                             cp->c_attr.va_type, cp->c_attr.va_rdev);
 854                         if (!null_cookie) {
 855                                 error = CFSOP_CHECK_COBJECT(fscp, cp, 0, cr);
 856                         }
 857                 }
 858         } else {
 859                 goto out;
 860         }
 861         cachefs_cnode_setlocalstats(cp);
 862 
 863 out:
 864         mutex_exit(&cp->c_statelock);
 865         if (error) {
 866                 if (cp->c_frontvp)
 867                         VN_RELE(cp->c_frontvp);
 868                 if (cp->c_backvp)
 869                         VN_RELE(cp->c_backvp);
 870                 if (cp->c_acldirvp)
 871                         VN_RELE(cp->c_acldirvp);
 872                 filegrp_rele(fgp);
 873                 rw_destroy(&cp->c_rwlock);
 874                 mutex_destroy(&cp->c_statelock);
 875                 cv_destroy(&cp->c_popcv);
 876                 mutex_destroy(&cp->c_iomutex);
 877                 cv_destroy(&cp->c_iocv);
 878         }
 879         return (error);
 880 }
 881 
 882 /*
 883  * Finds the cnode for the specified fileno and fid.
 884  * Creates the cnode if it does not exist.
 885  * The cnode is returned held.
 886  */
 887 int
 888 cachefs_cnode_make(cfs_cid_t *cidp, fscache_t *fscp, fid_t *cookiep,
 889         vattr_t *vap, vnode_t *backvp, cred_t *cr, int flag, cnode_t **cpp)
 890 {
 891         struct cnode *cp;
 892         int error;
 893         struct filegrp *fgp;
 894         struct cachefs_metadata *mdp;
 895         fid_t cookie;
 896 
 897 #ifdef CFSDEBUG
 898         CFS_DEBUG(CFSDEBUG_CNODE)
 899                 printf("cachefs_cnode_make: ENTER fileno %llu\n",
 900                     (u_longlong_t)cidp->cid_fileno);
 901 #endif
 902 
 903         /* get the file group that owns this file */
 904         mutex_enter(&fscp->fs_fslock);
 905         fgp = filegrp_list_find(fscp, cidp);
 906         if (fgp == NULL) {
 907                 fgp = filegrp_create(fscp, cidp);
 908                 filegrp_list_add(fscp, fgp);
 909         }
 910         filegrp_hold(fgp);
 911         mutex_exit(&fscp->fs_fslock);
 912 
 913         /* grab the cnode list lock */
 914         mutex_enter(&fgp->fg_cnodelock);
 915 
 916         if ((fgp->fg_flags & CFS_FG_READ) == 0)
 917                 flag |= CN_NOCACHE;
 918 
 919         error = 0;
 920         cp = NULL;
 921 
 922         /* look for the cnode on the cnode list */
 923         error = cachefs_cnode_find(fgp, cidp, cookiep, &cp, backvp, vap);
 924 
 925         /*
 926          * If there already is a cnode with this cid but a different cookie,
 927          * (or backvp) we're not going to be using the one we found.
 928          */
 929         if (error && CFS_ISFS_BACKFS_NFSV4(fscp)) {
 930                 ASSERT(MUTEX_HELD(&cp->c_statelock));
 931                 cachefs_cnode_stale(cp);
 932                 mutex_exit(&cp->c_statelock);
 933                 cp = NULL;
 934                 error = 0;
 935         } else if (error) {
 936                 ASSERT(cp);
 937                 ASSERT(cookiep);
 938 
 939                 mutex_exit(&cp->c_statelock);
 940 
 941                 /*
 942                  * If backvp is NULL then someone tried to use
 943                  * a stale cookie.
 944                  */
 945                 if (backvp == NULL) {
 946                         mutex_exit(&fgp->fg_cnodelock);
 947                         error = ESTALE;
 948                         goto out;
 949                 }
 950 
 951                 /* verify the backvp */
 952                 error = cachefs_getcookie(backvp, &cookie, NULL, cr, TRUE);
 953                 if (error ||
 954                     ((cookiep->fid_len != cookie.fid_len) ||
 955                     (bcmp(&cookiep->fid_data, cookie.fid_data,
 956                         (size_t)cookiep->fid_len) != 0))) {
 957                         mutex_exit(&fgp->fg_cnodelock);
 958                         error = ESTALE;
 959                         goto out;
 960                 }
 961 
 962                 /* make the old cnode give up its front file resources */
 963                 VN_HOLD(CTOV(cp));
 964                 (void) cachefs_sync_metadata(cp);
 965                 mutex_enter(&cp->c_statelock);
 966                 mdp = &cp->c_metadata;
 967                 if (mdp->md_rlno) {
 968                         /* XXX sam: should this assert be NOCACHE? */
 969                         /* XXX sam: maybe we should handle NOFILL as no-op */
 970                         ASSERT((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0);
 971 
 972                         /* if modified in the cache, move to lost+found */
 973                         if ((cp->c_attr.va_type == VREG) &&
 974                             (cp->c_metadata.md_rltype == CACHEFS_RL_MODIFIED)) {
 975                                 error = cachefs_cnode_lostfound(cp, NULL);
 976                                 if (error) {
 977                                         mutex_exit(&cp->c_statelock);
 978                                         VN_RELE(CTOV(cp));
 979                                         mutex_exit(&fgp->fg_cnodelock);
 980                                         error = ESTALE;
 981                                         goto out;
 982                                 }
 983                         }
 984 
 985                         /* else nuke the front file */
 986                         else {
 987                                 cachefs_cnode_stale(cp);
 988                         }
 989                 } else {
 990                         cachefs_cnode_stale(cp);
 991                 }
 992                 mutex_exit(&cp->c_statelock);
 993                 VN_RELE(CTOV(cp));
 994                 cp = NULL;
 995                 error = 0;
 996         }
 997 
 998 
 999         /* if the cnode does not exist */
1000         if (cp == NULL) {
1001                 /* XXX should we drop all locks for this? */
1002                 cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP);
1003 
1004                 error = cachefs_cnode_init(cidp, cp, fscp, fgp,
1005                     cookiep, vap, backvp, flag, cr);
1006                 if (error) {
1007                         mutex_exit(&fgp->fg_cnodelock);
1008                         vn_free(cp->c_vnode);
1009                         kmem_cache_free(cachefs_cnode_cache, cp);
1010                         goto out;
1011                 }
1012 
1013                 if (cp->c_metadata.md_rlno &&
1014                     (cp->c_metadata.md_rltype == CACHEFS_RL_GC) &&
1015                     ((fscp->fs_cache->c_flags & CACHE_NOFILL) == 0)) {
1016 #ifdef CFSDEBUG
1017                         cachefs_rlent_verify(fscp->fs_cache,
1018                             CACHEFS_RL_GC, cp->c_metadata.md_rlno);
1019 #endif /* CFSDEBUG */
1020                         cachefs_rlent_moveto(fscp->fs_cache,
1021                             CACHEFS_RL_ACTIVE, cp->c_metadata.md_rlno,
1022                             cp->c_metadata.md_frontblks);
1023                         cp->c_metadata.md_rltype = CACHEFS_RL_ACTIVE;
1024                         cp->c_flags |= CN_UPDATED;
1025                 }
1026 
1027                 cachefs_cnode_listadd(cp);
1028                 vn_exists(cp->c_vnode);
1029                 mutex_exit(&fgp->fg_cnodelock);
1030                 (void) fscache_cnodecnt(fscp, 1);
1031         }
1032 
1033         /* else if the cnode exists */
1034         else {
1035                 VN_HOLD(CTOV(cp));
1036 
1037                 /* remove from idle list if on it */
1038                 if (cp->c_flags & CN_IDLE) {
1039                         cp->c_flags &= ~CN_IDLE;
1040 
1041                         mutex_enter(&fscp->fs_idlelock);
1042                         cachefs_cnode_idlerem(cp);
1043                         mutex_exit(&fscp->fs_idlelock);
1044                         VN_RELE(CTOV(cp));
1045                         cp->c_ipending = 0;
1046                 }
1047                 mutex_exit(&cp->c_statelock);
1048                 mutex_exit(&fgp->fg_cnodelock);
1049         }
1050 
1051         /*
1052          * Assertion to ensure the cnode matches
1053          * the backvp and attribute type information.
1054          */
1055         ASSERT((CFS_ISFS_BACKFS_NFSV4(fscp) == 0) ||
1056                 ((cp->c_backvp == backvp) &&
1057                 (cp->c_attr.va_type == vap->va_type)));
1058 out:
1059         *cpp = ((error == 0) ? cp : NULL);
1060         filegrp_rele(fgp);
1061 
1062 #ifdef CFSDEBUG
1063         CFS_DEBUG(CFSDEBUG_CNODE)
1064                 printf("cachefs_cnode_make: EXIT cp %p, error %d\n",
1065                     (void *)*cpp, error);
1066 #endif
1067         return (error);
1068 }
1069 
1070 /*
1071  * cachefs_cid_inuse()
1072  *
1073  * returns nonzero if a cid has any data in the cache; either a cnode
1074  * or metadata.
1075  */
1076 
1077 int
1078 cachefs_cid_inuse(filegrp_t *fgp, cfs_cid_t *cidp)
1079 {
1080         cnode_t *cp;
1081         int status = 0;
1082 
1083         ASSERT(MUTEX_HELD(&fgp->fg_cnodelock));
1084 
1085         /*
1086          * Since we don't care about the cookie data, we don't care about any
1087          * status that find might return.
1088          */
1089 
1090         cp = NULL;
1091         (void) cachefs_cnode_find(fgp, cidp, NULL, &cp, NULL, NULL);
1092         if (cp != NULL) {
1093                 mutex_exit(&cp->c_statelock);
1094                 status = 1;
1095                 return (status);
1096         }
1097 
1098         /*
1099          * Don't want to use filegrp_read_metadata, since it will return
1100          * ENOENT if the metadata slot exists but hasn't been written to yet.
1101          * That condition still counts as the slot (metadata) being in use.
1102          * Instead, as long as the filegrp attrcache has been created and
1103          * there's a slot assigned for this cid, then the metadata is in use.
1104          */
1105         if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
1106             (filegrp_cid_to_slot(fgp, cidp) != 0))
1107                 status = 1;
1108 
1109         return (status);
1110 }
1111 
1112 /*
1113  * cachefs_fileno_inuse()
1114  *
1115  * returns nonzero if a fileno is known to the cache, as either a
1116  * local or a normal file.
1117  */
1118 
1119 int
1120 cachefs_fileno_inuse(fscache_t *fscp, ino64_t fileno)
1121 {
1122         cfs_cid_t cid;
1123         filegrp_t *fgp;
1124         int known = 0;
1125 
1126         ASSERT(MUTEX_HELD(&fscp->fs_fslock));
1127         cid.cid_fileno = fileno;
1128 
1129         /* if there's no filegrp for this cid range, then there's no data */
1130         fgp = filegrp_list_find(fscp, &cid);
1131         if (fgp == NULL)
1132                 return (known);
1133 
1134         filegrp_hold(fgp);
1135         mutex_enter(&fgp->fg_cnodelock);
1136 
1137         cid.cid_flags = CFS_CID_LOCAL;
1138         if (cachefs_cid_inuse(fgp, &cid)) {
1139                 known = 1;
1140                 goto out;
1141         }
1142         cid.cid_flags = 0;
1143         if (cachefs_cid_inuse(fgp, &cid))
1144                 known = 1;
1145 out:
1146         mutex_exit(&fgp->fg_cnodelock);
1147         filegrp_rele(fgp);
1148         return (known);
1149 }
1150 
1151 /*
1152  * Creates a cnode from an unused inode in the cache.
1153  * The cnode is returned held.
1154  */
1155 int
1156 cachefs_cnode_create(fscache_t *fscp, vattr_t *vap, int flag, cnode_t **cpp)
1157 {
1158         struct cnode *cp;
1159         int error, found;
1160         struct filegrp *fgp;
1161         cfs_cid_t cid, cid2;
1162 
1163         ASSERT(CFS_ISFS_SNR(fscp));
1164         ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1165 
1166         cid.cid_flags = CFS_CID_LOCAL;
1167         cid2.cid_flags = 0;
1168 
1169         /* find an unused local file in the cache */
1170         for (;;) {
1171                 mutex_enter(&fscp->fs_fslock);
1172 
1173                 /* make sure we did not wrap */
1174                 fscp->fs_info.fi_localfileno++;
1175                 if (fscp->fs_info.fi_localfileno == 0)
1176                         fscp->fs_info.fi_localfileno = 3;
1177                 cid.cid_fileno = fscp->fs_info.fi_localfileno;
1178                 fscp->fs_flags |= CFS_FS_DIRTYINFO;
1179 
1180                 /* avoid fileno conflict in non-local space */
1181                 cid2.cid_fileno = cid.cid_fileno;
1182                 fgp = filegrp_list_find(fscp, &cid2);
1183                 if (fgp != NULL) {
1184                         filegrp_hold(fgp);
1185                         mutex_enter(&fgp->fg_cnodelock);
1186                         found = cachefs_cid_inuse(fgp, &cid2);
1187                         mutex_exit(&fgp->fg_cnodelock);
1188                         filegrp_rele(fgp);
1189                         if (found) {
1190                                 mutex_exit(&fscp->fs_fslock);
1191                                 continue;
1192                         }
1193                 }
1194 
1195                 /* get the file group that owns this fileno */
1196                 fgp = filegrp_list_find(fscp, &cid);
1197                 if (fgp == NULL) {
1198                         fgp = filegrp_create(fscp, &cid);
1199                         filegrp_list_add(fscp, fgp);
1200                 }
1201 
1202                 /* see if there is any room left in this file group */
1203                 mutex_enter(&fgp->fg_mutex);
1204                 if (fgp->fg_header &&
1205                     (fgp->fg_header->ach_count ==
1206                     fscp->fs_info.fi_fgsize)) {
1207                         /* no more room, set up for the next file group */
1208                         fscp->fs_info.fi_localfileno = fgp->fg_id.cid_fileno +
1209                             fscp->fs_info.fi_fgsize;
1210                         mutex_exit(&fgp->fg_mutex);
1211                         mutex_exit(&fscp->fs_fslock);
1212                         continue;
1213                 }
1214                 mutex_exit(&fgp->fg_mutex);
1215 
1216                 filegrp_hold(fgp);
1217                 mutex_exit(&fscp->fs_fslock);
1218 
1219                 ASSERT((fgp->fg_flags &
1220                     (CFS_FG_READ | CFS_FG_WRITE)) ==
1221                     (CFS_FG_READ | CFS_FG_WRITE));
1222 
1223                 /* grab the cnode list lock */
1224                 mutex_enter(&fgp->fg_cnodelock);
1225 
1226                 if ((fgp->fg_flags & CFS_FG_READ) == 0)
1227                         flag |= CN_NOCACHE;
1228 
1229                 /* keep looking if a cnode or metadata exist for this fileno */
1230                 if (cachefs_cid_inuse(fgp, &cid)) {
1231                         mutex_exit(&fgp->fg_cnodelock);
1232                         filegrp_rele(fgp);
1233 #ifdef CFSDEBUG
1234                         CFS_DEBUG(CFSDEBUG_CNODE)
1235                                 cmn_err(CE_NOTE, "cachefs_cnode_create: "
1236                                     "fileno %llu exists.\n",
1237                                     (u_longlong_t)cid.cid_fileno);
1238 #endif
1239                         continue;
1240                 }
1241                 break;
1242         }
1243 
1244         vap->va_nodeid = cid.cid_fileno;
1245 
1246         /* create space for the cnode */
1247         cp = kmem_cache_alloc(cachefs_cnode_cache, KM_SLEEP);
1248 
1249         /* set up the cnode */
1250         error = cachefs_cnode_init(&cid, cp, fscp, fgp,
1251             &cp->c_cookie, vap, NULL, flag, kcred);
1252         if (error) {
1253                 mutex_exit(&fgp->fg_cnodelock);
1254                 vn_free(cp->c_vnode);
1255                 kmem_cache_free(cachefs_cnode_cache, cp);
1256                 goto out;
1257         }
1258 
1259         /* save copy of fileno that is returned to the user */
1260         cp->c_metadata.md_flags |= MD_LOCALFILENO;
1261         cp->c_metadata.md_localfileno = cid.cid_fileno;
1262         cp->c_flags |= CN_UPDATED;
1263 
1264         cachefs_cnode_listadd(cp);
1265         mutex_exit(&fgp->fg_cnodelock);
1266         (void) fscache_cnodecnt(fscp, 1);
1267 
1268 out:
1269         *cpp = ((error == 0) ? cp : NULL);
1270         filegrp_rele(fgp);
1271         return (error);
1272 }
1273 
1274 /*
1275  * Moves the cnode to its new location in the cache.
1276  * Before calling this routine other steps must be taken
1277  * to ensure that other file system routines that operate
1278  * on cnodes do not run.
1279  */
1280 void
1281 cachefs_cnode_move(cnode_t *cp)
1282 {
1283         fscache_t *fscp = C_TO_FSCACHE(cp);
1284         cfs_cid_t cid;
1285         filegrp_t *fgp;
1286         filegrp_t *ofgp = cp->c_filegrp;
1287         struct cachefs_metadata *mdp;
1288         cnode_t *xcp;
1289         char oname[CFS_FRONTFILE_NAME_SIZE];
1290         char nname[CFS_FRONTFILE_NAME_SIZE];
1291         int ffnuke = 0;
1292         int error;
1293 
1294         ASSERT(CFS_ISFS_SNR(fscp));
1295         ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1296         ASSERT(cp->c_id.cid_flags & CFS_CID_LOCAL);
1297         ASSERT(cp->c_attr.va_nodeid != 0);
1298 
1299         /* construct the cid of the new file location */
1300         cid.cid_fileno = cp->c_attr.va_nodeid;
1301         cid.cid_flags = 0;
1302 
1303         /* see if there already is a file occupying our slot */
1304         error = cachefs_cnode_make(&cid, fscp, NULL, NULL, NULL, kcred,
1305             0, &xcp);
1306         if (error == 0) {
1307                 mutex_enter(&xcp->c_statelock);
1308                 cachefs_cnode_stale(xcp);
1309                 mutex_exit(&xcp->c_statelock);
1310                 VN_RELE(CTOV(xcp));
1311                 xcp = NULL;
1312                 error = 0;
1313         }
1314 
1315         /* get the file group that this file is moving to */
1316         mutex_enter(&fscp->fs_fslock);
1317         fgp = filegrp_list_find(fscp, &cid);
1318         if (fgp == NULL) {
1319                 fgp = filegrp_create(fscp, &cid);
1320                 filegrp_list_add(fscp, fgp);
1321         }
1322         filegrp_hold(fgp);
1323         mutex_exit(&fscp->fs_fslock);
1324 
1325         /* XXX fix to not have to create metadata to hold rl slot */
1326         /* get a metadata slot in the new file group */
1327         if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
1328                 (void) filegrp_allocattr(fgp);
1329         }
1330         /* XXX can fix create_metadata to call allocattr if necessary? */
1331         error = filegrp_create_metadata(fgp, &cp->c_metadata, &cid);
1332         if (error)
1333                 ffnuke = 1;
1334         if ((ffnuke == 0) && filegrp_ffhold(fgp))
1335                 ffnuke = 1;
1336 
1337         /* move the front file to the new file group */
1338         if ((ffnuke == 0) && (cp->c_metadata.md_flags & MD_FILE)) {
1339                 make_ascii_name(&cp->c_id, oname);
1340                 make_ascii_name(&cid, nname);
1341                 error = VOP_RENAME(ofgp->fg_dirvp, oname, fgp->fg_dirvp,
1342                         nname, kcred, NULL, 0);
1343                 if (error) {
1344                         ffnuke = 1;
1345 #ifdef CFSDEBUG
1346                         if (error != ENOSPC) {
1347                                 CFS_DEBUG(CFSDEBUG_CNODE)
1348                                         printf("cachefs: cnode_move "
1349                                             "1: error %d\n", error);
1350                         }
1351 #endif
1352                 }
1353         }
1354 
1355         /* remove the file from the old file group */
1356         mutex_enter(&ofgp->fg_cnodelock);
1357         mutex_enter(&cp->c_statelock);
1358         if (cp->c_frontvp) {
1359                 VN_RELE(cp->c_frontvp);
1360                 cp->c_frontvp = NULL;
1361         }
1362         if (cp->c_acldirvp) {
1363                 VN_RELE(cp->c_acldirvp);
1364                 cp->c_acldirvp = NULL;
1365         }
1366         mdp = &cp->c_metadata;
1367         if (mdp->md_rlno) {
1368                 if (ffnuke) {
1369                         cachefs_removefrontfile(mdp, &cp->c_id, ofgp);
1370                         cachefs_rlent_moveto(fscp->fs_cache,
1371                             CACHEFS_RL_FREE, mdp->md_rlno, 0);
1372                         mdp->md_rlno = 0;
1373                         mdp->md_rltype = CACHEFS_RL_NONE;
1374                 } else {
1375                         filegrp_ffrele(ofgp);
1376                 }
1377         }
1378         if (ffnuke)
1379                 mdp->md_flags &= ~MD_PACKED;
1380         if ((cp->c_flags & CN_ALLOC_PENDING) == 0) {
1381                 (void) filegrp_destroy_metadata(ofgp, &cp->c_id);
1382                 cp->c_flags |= CN_ALLOC_PENDING;
1383         }
1384         cachefs_cnode_listrem(cp);
1385         cp->c_filegrp = NULL;
1386         mutex_exit(&cp->c_statelock);
1387         mutex_exit(&ofgp->fg_cnodelock);
1388 
1389         /* add the cnode to the new file group */
1390         mutex_enter(&fgp->fg_cnodelock);
1391         mutex_enter(&cp->c_statelock);
1392         cp->c_id = cid;
1393         cp->c_filegrp = fgp;
1394         cp->c_flags |= CN_UPDATED;
1395         mutex_exit(&cp->c_statelock);
1396         cachefs_cnode_listadd(cp);
1397         if (mdp->md_rlno)
1398                 cachefs_rl_changefileno(fscp->fs_cache, mdp->md_rlno,
1399                     cp->c_id.cid_fileno);
1400         mutex_exit(&fgp->fg_cnodelock);
1401 
1402         filegrp_rele(ofgp);
1403 }
1404 
1405 /*
1406  * Syncs out the specified cnode.
1407  * Only called via cnode_traverse from fscache_sync
1408  */
1409 void
1410 cachefs_cnode_sync(cnode_t *cp)
1411 {
1412         vnode_t *vp = CTOV(cp);
1413         int error = 0;
1414         fscache_t *fscp = C_TO_FSCACHE(cp);
1415         int held = 0;
1416 
1417         if (cp->c_flags & (CN_STALE | CN_DESTROY))
1418                 return;
1419 
1420         if (fscp->fs_backvfsp && fscp->fs_backvfsp->vfs_flag & VFS_RDONLY)
1421                 return;
1422 
1423         for (;;) {
1424                 /* get (or renew) access to the file system */
1425                 if (held) {
1426                         cachefs_cd_release(fscp);
1427                         held = 0;
1428                 }
1429                 /*
1430                  * Getting file system access for reading is really cheating.
1431                  * However we are getting called from sync so we do not
1432                  * want to hang up if the cachefsd is not running.
1433                  */
1434                 error = cachefs_cd_access(fscp, 0, 0);
1435                 if (error)
1436                         break;
1437                 held = 1;
1438 
1439                 /* if a regular file, write out the pages */
1440                 if ((vp->v_type == VREG) && vn_has_cached_data(vp)) {
1441                         ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
1442                         error = cachefs_putpage_common(vp, (offset_t)0,
1443                             0, 0, kcred);
1444                         if (CFS_TIMEOUT(fscp, error)) {
1445                                 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
1446                                         cachefs_cd_release(fscp);
1447                                         held = 0;
1448                                         cachefs_cd_timedout(fscp);
1449                                         continue;
1450                                 } else {
1451                                         /* cannot push, give up */
1452                                         break;
1453                                 }
1454                         }
1455 
1456                         /* clear the cnode error if putpage worked */
1457                         if ((error == 0) && cp->c_error) {
1458                                 mutex_enter(&cp->c_statelock);
1459                                 cp->c_error = 0;
1460                                 mutex_exit(&cp->c_statelock);
1461                         }
1462 
1463                         if (error)
1464                                 break;
1465                 }
1466 
1467                 /* if connected, sync the backvp */
1468                 if ((fscp->fs_cdconnected == CFS_CD_CONNECTED) &&
1469                     cp->c_backvp) {
1470                         mutex_enter(&cp->c_statelock);
1471                         if (cp->c_backvp) {
1472                                 error = VOP_FSYNC(cp->c_backvp, FSYNC, kcred,
1473                                     NULL);
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, NULL, NULL, NULL);
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, NULL, NULL, NULL);
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, NULL, 0);
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                                 /* reacquire 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                         /* reacquire 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, NULL);
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 }