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