Home | History | Annotate | Download | only in cachefs
      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 }
   1966