xref: /titanic_44/usr/src/uts/common/fs/cachefs/cachefs_cnode.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
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
cachefs_cnode_idle(struct vnode * vp,cred_t * cr)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
cachefs_cnode_idleclean(fscache_t * fscp,int unmount)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
cachefs_cnode_inactive(register struct vnode * vp,cred_t * cr)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
cachefs_cnode_listadd(struct cnode * cp)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
cachefs_cnode_listrem(struct cnode * cp)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
cachefs_cnode_idleadd(struct cnode * cp)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
cachefs_cnode_idlerem(struct cnode * cp)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
cachefs_cnode_find(filegrp_t * fgp,cfs_cid_t * cidp,fid_t * cookiep,struct cnode ** cpp,struct vnode * backvp,vattr_t * vap)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
cachefs_cnode_init(cfs_cid_t * cidp,cnode_t * cp,fscache_t * fscp,filegrp_t * fgp,fid_t * cookiep,vattr_t * vap,vnode_t * backvp,int flag,cred_t * cr)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
cachefs_cnode_make(cfs_cid_t * cidp,fscache_t * fscp,fid_t * cookiep,vattr_t * vap,vnode_t * backvp,cred_t * cr,int flag,cnode_t ** cpp)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
cachefs_cid_inuse(filegrp_t * fgp,cfs_cid_t * cidp)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
cachefs_fileno_inuse(fscache_t * fscp,ino64_t fileno)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
cachefs_cnode_create(fscache_t * fscp,vattr_t * vap,int flag,cnode_t ** cpp)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
cachefs_cnode_move(cnode_t * cp)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
cachefs_cnode_sync(cnode_t * cp)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
cachefs_cnode_lostfound(cnode_t * cp,char * rname)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
cachefs_cnode_traverse(fscache_t * fscp,void (* routinep)(cnode_t *))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
cachefs_cnode_disable_caching(struct cnode * cp)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
cnode_enable_caching(struct cnode * cp)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
cachefs_enable_caching(struct fscache * fscp)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
cachefs_cnode_stale(cnode_t * cp)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
cachefs_cnode_setlocalstats(cnode_t * cp)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