xref: /onnv-gate/usr/src/uts/common/fs/cachefs/cachefs_filegrp.c (revision 5331:3047ad28a67b)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54356Scasper  * Common Development and Distribution License (the "License").
64356Scasper  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
224356Scasper  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/param.h>
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/systm.h>
300Sstevel@tonic-gate #include <sys/cred.h>
310Sstevel@tonic-gate #include <sys/proc.h>
320Sstevel@tonic-gate #include <sys/user.h>
330Sstevel@tonic-gate #include <sys/vfs.h>
340Sstevel@tonic-gate #include <sys/vnode.h>
350Sstevel@tonic-gate #include <sys/pathname.h>
360Sstevel@tonic-gate #include <sys/uio.h>
370Sstevel@tonic-gate #include <sys/tiuser.h>
380Sstevel@tonic-gate #include <sys/sysmacros.h>
390Sstevel@tonic-gate #include <sys/kmem.h>
400Sstevel@tonic-gate #include <sys/mount.h>
410Sstevel@tonic-gate #include <sys/ioctl.h>
420Sstevel@tonic-gate #include <sys/statvfs.h>
430Sstevel@tonic-gate #include <sys/errno.h>
440Sstevel@tonic-gate #include <sys/debug.h>
450Sstevel@tonic-gate #include <sys/cmn_err.h>
460Sstevel@tonic-gate #include <sys/utsname.h>
470Sstevel@tonic-gate #include <sys/bootconf.h>
480Sstevel@tonic-gate #include <sys/modctl.h>
490Sstevel@tonic-gate #include <sys/file.h>
500Sstevel@tonic-gate #include <sys/stat.h>
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #include <vm/hat.h>
530Sstevel@tonic-gate #include <vm/as.h>
540Sstevel@tonic-gate #include <vm/page.h>
550Sstevel@tonic-gate #include <vm/pvn.h>
560Sstevel@tonic-gate #include <vm/seg.h>
570Sstevel@tonic-gate #include <vm/seg_map.h>
580Sstevel@tonic-gate #include <vm/seg_vn.h>
590Sstevel@tonic-gate #include <vm/rm.h>
600Sstevel@tonic-gate #include <sys/fs/cachefs_fs.h>
610Sstevel@tonic-gate #include <sys/fs/cachefs_log.h>
620Sstevel@tonic-gate 
630Sstevel@tonic-gate struct kmem_cache *cachefs_filegrp_cache = NULL;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate #if (defined(_SYSCALL32_IMPL) || defined(_LP64))
660Sstevel@tonic-gate 
670Sstevel@tonic-gate #define	CACHEFS_ALLOC_CFS_METADATA(p, inp)				\
680Sstevel@tonic-gate 	p = cachefs_kmem_zalloc(sizeof (struct cfs_cachefs_metadata), KM_SLEEP)
690Sstevel@tonic-gate 
700Sstevel@tonic-gate #define	CACHEFS_FREE_CFS_METADATA(p)					\
710Sstevel@tonic-gate 	cachefs_kmem_free(p, sizeof (struct cfs_cachefs_metadata))
720Sstevel@tonic-gate 
730Sstevel@tonic-gate /* CACHEFS_COPY_COMMON_METADATA_FIELDS - common code for the metadata copy */
740Sstevel@tonic-gate #define	CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp)		\
750Sstevel@tonic-gate 	(outmdp)->md_aclclass = (inmdp)->md_aclclass;			\
760Sstevel@tonic-gate 	CACHEFS_FID_COPY(&(inmdp)->md_cookie, &(outmdp)->md_cookie);	\
770Sstevel@tonic-gate 	(outmdp)->md_flags = (inmdp)->md_flags;				\
780Sstevel@tonic-gate 	(outmdp)->md_rlno = (inmdp)->md_rlno;				\
790Sstevel@tonic-gate 	(outmdp)->md_rltype = (inmdp)->md_rltype;			\
800Sstevel@tonic-gate 	(outmdp)->md_consttype = (inmdp)->md_consttype;			\
810Sstevel@tonic-gate 	CACHEFS_FID_COPY(&(inmdp)->md_fid, &(outmdp)->md_fid);		\
820Sstevel@tonic-gate 	(outmdp)->md_frontblks = (inmdp)->md_frontblks;			\
830Sstevel@tonic-gate 	(outmdp)->md_gen = (inmdp)->md_gen;				\
840Sstevel@tonic-gate 	(outmdp)->md_parent = (inmdp)->md_parent;			\
850Sstevel@tonic-gate 	(outmdp)->md_resettimes = (inmdp)->md_resettimes;		\
860Sstevel@tonic-gate 	(outmdp)->md_localfileno = (inmdp)->md_localfileno;		\
870Sstevel@tonic-gate 	(outmdp)->md_resetfileno = (inmdp)->md_resetfileno;		\
880Sstevel@tonic-gate 	(outmdp)->md_seq = (inmdp)->md_seq;				\
890Sstevel@tonic-gate 	(outmdp)->md_allocents = (inmdp)->md_allocents;			\
900Sstevel@tonic-gate 	bcopy(&(inmdp)->md_allocinfo, &(outmdp)->md_allocinfo,		\
910Sstevel@tonic-gate 	    MIN(sizeof (inmdp)->md_allocinfo, sizeof (outmdp)->md_allocinfo))
920Sstevel@tonic-gate 
930Sstevel@tonic-gate #define	CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error)	\
940Sstevel@tonic-gate 	CACHEFS_VATTR_TO_CFS_VATTR_COPY(&(inmdp)->md_vattr,		\
950Sstevel@tonic-gate 		&(outmdp)->md_vattr, error);				\
960Sstevel@tonic-gate 	CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_timestamp,		\
970Sstevel@tonic-gate 		&(outmdp)->md_timestamp, error);			\
980Sstevel@tonic-gate 	CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_x_time,			\
990Sstevel@tonic-gate 		&(outmdp)->md_x_time, error);				\
1000Sstevel@tonic-gate 	CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localmtime,		\
1010Sstevel@tonic-gate 		&(outmdp)->md_localmtime, error);			\
1020Sstevel@tonic-gate 	CACHEFS_TS_TO_CFS_TS_COPY(&(inmdp)->md_localctime,		\
1030Sstevel@tonic-gate 		&(outmdp)->md_localctime, error);			\
1040Sstevel@tonic-gate 	CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp)
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate #define	CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp)		\
1070Sstevel@tonic-gate 	CACHEFS_CFS_VATTR_TO_VATTR_COPY(&(inmdp)->md_vattr,		\
1080Sstevel@tonic-gate 		&(outmdp)->md_vattr);					\
1090Sstevel@tonic-gate 	CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_timestamp,		\
1100Sstevel@tonic-gate 		&(outmdp)->md_timestamp);				\
1110Sstevel@tonic-gate 	CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_x_time,			\
1120Sstevel@tonic-gate 		&(outmdp)->md_x_time);					\
1130Sstevel@tonic-gate 	CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localmtime,		\
1140Sstevel@tonic-gate 		&(outmdp)->md_localmtime);				\
1150Sstevel@tonic-gate 	CACHEFS_CFS_TS_TO_TS_COPY(&(inmdp)->md_localctime,		\
1160Sstevel@tonic-gate 		&(outmdp)->md_localctime);				\
1170Sstevel@tonic-gate 	CACHEFS_COPY_COMMON_METADATA_FIELDS(inmdp, outmdp)
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate #else /* not (_SYSCALL32_IMPL || _LP64) */
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate #define	CACHEFS_ALLOC_CFS_METADATA(p, inp)				\
1220Sstevel@tonic-gate 	p = (cfs_cachefs_metadata_t *)(inp)
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate #define	CACHEFS_FREE_CFS_METADATA(p)
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate #define	CACHEFS_COPY_METADATA_TO_CFS_METADATA(inmdp, outmdp, error)
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate #define	CACHEFS_COPY_CFS_METADATA_TO_METADATA(inmdp, outmdp)
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate #endif /* _SYSCALL32_IMPL || _LP64 */
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate /* forward references */
1330Sstevel@tonic-gate int filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt);
1340Sstevel@tonic-gate int filegrpattr_find(struct filegrp *fgp);
1350Sstevel@tonic-gate int filegrpattr_create(struct filegrp *fgp);
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate int
1380Sstevel@tonic-gate /*ARGSUSED*/
filegrp_cache_create(void * voidp,void * cdrarg,int kmflags)1390Sstevel@tonic-gate filegrp_cache_create(void *voidp, void *cdrarg, int kmflags)
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate 	filegrp_t *fgp = (filegrp_t *)voidp;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	mutex_init(&fgp->fg_mutex, NULL, MUTEX_DEFAULT, NULL);
1440Sstevel@tonic-gate 	mutex_init(&fgp->fg_cnodelock, NULL, MUTEX_DEFAULT, NULL);
1450Sstevel@tonic-gate 	return (0);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate void
1490Sstevel@tonic-gate /*ARGSUSED*/
filegrp_cache_destroy(void * voidp,void * cdrarg)1500Sstevel@tonic-gate filegrp_cache_destroy(void *voidp, void *cdrarg)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	filegrp_t *fgp = (filegrp_t *)voidp;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	mutex_destroy(&fgp->fg_mutex);
1550Sstevel@tonic-gate 	mutex_destroy(&fgp->fg_cnodelock);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate /*
1590Sstevel@tonic-gate  * ------------------------------------------------------------------
1600Sstevel@tonic-gate  *
1610Sstevel@tonic-gate  *		filegrp_create
1620Sstevel@tonic-gate  *
1630Sstevel@tonic-gate  * Description:
1640Sstevel@tonic-gate  *	Creates a filegrp object for the specified fscache.
1650Sstevel@tonic-gate  *	The CFS_FG_ALLOC_{ATTR, FILE} bits will be set in fg_flags
1660Sstevel@tonic-gate  *	if the cache is in NOCACHE and NOFILL mode or if
1670Sstevel@tonic-gate  *	the directory does not exist yet.
1680Sstevel@tonic-gate  *	The filegrp object maintains a reference to the specified
1690Sstevel@tonic-gate  *	fscache.
1700Sstevel@tonic-gate  * Arguments:
1710Sstevel@tonic-gate  *	fscp	fscache to create the file group in
1720Sstevel@tonic-gate  *	cidp	start cid for the file group
1730Sstevel@tonic-gate  * Returns:
1740Sstevel@tonic-gate  *	Returns the created filegrp object.
1750Sstevel@tonic-gate  * Preconditions:
1760Sstevel@tonic-gate  *	precond(fscp)
1770Sstevel@tonic-gate  *	precond(cidp)
1780Sstevel@tonic-gate  *	precond(fscp->fs_info.fi_fgsize > 0)
1790Sstevel@tonic-gate  */
1800Sstevel@tonic-gate #define	Bugid_1249206_notfixed
1810Sstevel@tonic-gate #ifdef Bugid_1249206_notfixed
1820Sstevel@tonic-gate int bugid_1249206 = 0;
1830Sstevel@tonic-gate #endif
1840Sstevel@tonic-gate filegrp_t *
filegrp_create(struct fscache * fscp,cfs_cid_t * cidp)1850Sstevel@tonic-gate filegrp_create(struct fscache *fscp, cfs_cid_t *cidp)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	filegrp_t *fgp;
1880Sstevel@tonic-gate 	int fgsize;
1890Sstevel@tonic-gate 	int flags;
1900Sstevel@tonic-gate 	ino64_t nfgsize;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	fgsize = fscp->fs_info.fi_fgsize;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	fgp = (filegrp_t *)
1950Sstevel@tonic-gate 	    kmem_cache_alloc(cachefs_filegrp_cache, KM_SLEEP);
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	fgp->fg_flags = CFS_FG_ALLOC_ATTR | CFS_FG_ALLOC_FILE;
1980Sstevel@tonic-gate 	fgp->fg_count = 0;
1990Sstevel@tonic-gate 	fgp->fg_id = *cidp;
2000Sstevel@tonic-gate #ifdef Bugid_1249206_notfixed
2010Sstevel@tonic-gate 	if (bugid_1249206)
2020Sstevel@tonic-gate 		cmn_err(CE_CONT, "fg_id assigned value is %" PRId64 "\n",
2030Sstevel@tonic-gate 		    fgp->fg_id.cid_fileno);
2040Sstevel@tonic-gate #endif
2050Sstevel@tonic-gate 	nfgsize = (fgp->fg_id.cid_fileno / (ino64_t)fgsize);
2060Sstevel@tonic-gate 	fgp->fg_id.cid_fileno = (ino64_t)(nfgsize * (ino64_t)fgsize);
2070Sstevel@tonic-gate #ifdef Bugid_1249206_notfixed
2080Sstevel@tonic-gate 	if (bugid_1249206) {
2090Sstevel@tonic-gate 		cmn_err(CE_CONT,
2100Sstevel@tonic-gate 		    "cid_fileno for fscp %p fgp %p is %" PRId64 "\n",
2110Sstevel@tonic-gate 		    (void *)fscp, (void *)fgp,
2120Sstevel@tonic-gate 		    fgp->fg_id.cid_fileno);
2130Sstevel@tonic-gate 		cmn_err(CE_CONT,
2140Sstevel@tonic-gate 		    "sent fileno is %" PRId64 " fgsize %d nfgsize %" PRId64
2150Sstevel@tonic-gate 		    "\n", cidp->cid_fileno, fgsize, nfgsize);
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate #endif
2180Sstevel@tonic-gate 	fgp->fg_fscp = fscp;
2190Sstevel@tonic-gate 	fgp->fg_cnodelist = NULL;
2200Sstevel@tonic-gate 	fgp->fg_next = NULL;
2210Sstevel@tonic-gate 	fgp->fg_dirvp = NULL;
2220Sstevel@tonic-gate 	fgp->fg_attrvp = NULL;
2230Sstevel@tonic-gate 	fgp->fg_header = NULL;
2240Sstevel@tonic-gate 	fgp->fg_offsets = NULL;
2250Sstevel@tonic-gate 	fgp->fg_alloclist = NULL;
2260Sstevel@tonic-gate 
227*5331Samw 	fgp->fg_headersize = (uint_t)sizeof (struct attrcache_header) +
228*5331Samw 	    (fgsize * (uint_t)sizeof (struct attrcache_index)) +
2290Sstevel@tonic-gate 	    ((fgsize + 7) >> 3);
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	fgp->fg_filesize = fgp->fg_headersize +
232*5331Samw 	    (fgsize * (uint_t)sizeof (struct cfs_cachefs_metadata));
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	flags = fscp->fs_flags;
2350Sstevel@tonic-gate 	if (flags & CFS_FS_READ) {
2360Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_READ;
2370Sstevel@tonic-gate 		if (flags & CFS_FS_WRITE) {
2380Sstevel@tonic-gate 			fgp->fg_flags |= CFS_FG_WRITE;
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 	}
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_READ) {
2430Sstevel@tonic-gate 		/* find the attrcache file and frontfile directory */
2440Sstevel@tonic-gate 		(void) filegrpattr_find(fgp);
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 		/*
2470Sstevel@tonic-gate 		 * XXX: we can tell from the file count in the attrcache
2480Sstevel@tonic-gate 		 * whether we can expect to find a front file dir or
2490Sstevel@tonic-gate 		 * not.  If not, we can save the lookup here...
2500Sstevel@tonic-gate 		 */
2510Sstevel@tonic-gate 		(void) filegrpdir_find(fgp);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	return (fgp);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate  * ------------------------------------------------------------------
2590Sstevel@tonic-gate  *
2600Sstevel@tonic-gate  *		filegrp_destroy
2610Sstevel@tonic-gate  *
2620Sstevel@tonic-gate  * Description:
2630Sstevel@tonic-gate  *	Destroys the filegrp object and releases any kernel
2640Sstevel@tonic-gate  *	resource associated with it.
2650Sstevel@tonic-gate  *	Additionally if the on disk file group directory does
2660Sstevel@tonic-gate  *	not contain any front files it is removed.
2670Sstevel@tonic-gate  * Arguments:
2680Sstevel@tonic-gate  *	fgp	filegrp object to destroy
2690Sstevel@tonic-gate  * Returns:
2700Sstevel@tonic-gate  * Preconditions:
2710Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
2720Sstevel@tonic-gate  *	precond(fgp->fg_count == 0)
2730Sstevel@tonic-gate  *	precond(fgp->fg_next == NULL)
2740Sstevel@tonic-gate  */
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate void
filegrp_destroy(filegrp_t * fgp)2770Sstevel@tonic-gate filegrp_destroy(filegrp_t *fgp)
2780Sstevel@tonic-gate {
2790Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
2800Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
2810Sstevel@tonic-gate 	char *fname;
2820Sstevel@tonic-gate 	int error;
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 	ASSERT(fgp->fg_count == 0);
2850Sstevel@tonic-gate 	ASSERT(fgp->fg_next == NULL);
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if (fgp->fg_attrvp) {
2880Sstevel@tonic-gate 		if (fgp->fg_flags & CFS_FG_UPDATED) {
2890Sstevel@tonic-gate 			error = filegrp_sync(fgp);
2900Sstevel@tonic-gate 			if (error)
2910Sstevel@tonic-gate 				cmn_err(CE_WARN,
2920Sstevel@tonic-gate 				    "cachefs: UFS error on cache, "
2930Sstevel@tonic-gate 				    "run fsck %d", error);
2940Sstevel@tonic-gate 		}
2950Sstevel@tonic-gate 		VN_RELE(fgp->fg_attrvp);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	if (fgp->fg_header) {
2980Sstevel@tonic-gate 		/*
2990Sstevel@tonic-gate 		 * If there are no attrcache entries in use and
3000Sstevel@tonic-gate 		 * if we can modify the cache.
3010Sstevel@tonic-gate 		 */
3020Sstevel@tonic-gate 		if ((fgp->fg_header->ach_count == 0) &&
3030Sstevel@tonic-gate 		    (fgp->fg_flags & CFS_FG_WRITE)) {
3040Sstevel@tonic-gate 			ASSERT(fgp->fg_header->ach_nffs == 0);
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 			/* remove attrcache file from the rl list */
3070Sstevel@tonic-gate 			ASSERT(fgp->fg_header->ach_rl_current ==
3080Sstevel@tonic-gate 			    CACHEFS_RL_GC);
3090Sstevel@tonic-gate #ifdef CFSDEBUG
3100Sstevel@tonic-gate 			cachefs_rlent_verify(fscp->fs_cache, CACHEFS_RL_GC,
3110Sstevel@tonic-gate 			    fgp->fg_header->ach_rlno);
3120Sstevel@tonic-gate #endif /* CFSDEBUG */
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 			/*
3150Sstevel@tonic-gate 			 * XXX sam: since we're blowing away the
3160Sstevel@tonic-gate 			 * attrcache file, i guess i don't need to set
3170Sstevel@tonic-gate 			 * ach_rl_current to CACHEFS_RL_NONE and
3180Sstevel@tonic-gate 			 * sync the attrcache file, right?
3190Sstevel@tonic-gate 			 *
3200Sstevel@tonic-gate 			 * fgp->fg_header->ach_rl_current = CACHEFS_RL_NONE;
3210Sstevel@tonic-gate 			 * fgp->fg_flags |= CFS_FG_UPDATED;
3220Sstevel@tonic-gate 			 */
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 			/* remove the attrcache file */
3250Sstevel@tonic-gate 			make_ascii_name(&fgp->fg_id, name);
3260Sstevel@tonic-gate 			fname = name;
327*5331Samw 			error = VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred,
328*5331Samw 			    NULL, 0);
3290Sstevel@tonic-gate 			if (error) {
3300Sstevel@tonic-gate 				cmn_err(CE_WARN,
3310Sstevel@tonic-gate 				    "cachefs: error in cache, run fsck");
3320Sstevel@tonic-gate 			} else {
3330Sstevel@tonic-gate 				cachefs_freefile(fscp->fs_cache);
3340Sstevel@tonic-gate 				cachefs_freeblocks(fscp->fs_cache,
3350Sstevel@tonic-gate 				    fgp->fg_header->ach_nblks, CACHEFS_RL_GC);
3360Sstevel@tonic-gate 				cachefs_rlent_moveto(fscp->fs_cache,
3370Sstevel@tonic-gate 				    CACHEFS_RL_FREE, fgp->fg_header->ach_rlno,
3380Sstevel@tonic-gate 				    0);
3390Sstevel@tonic-gate 			}
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 		cachefs_kmem_free(fgp->fg_header, fgp->fg_headersize);
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 	if (fgp->fg_dirvp) {
3440Sstevel@tonic-gate 		VN_RELE(fgp->fg_dirvp);
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 	kmem_cache_free(cachefs_filegrp_cache, fgp);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate  * ------------------------------------------------------------------
3510Sstevel@tonic-gate  *
3520Sstevel@tonic-gate  *		filegrp_allocattr
3530Sstevel@tonic-gate  *
3540Sstevel@tonic-gate  * Description:
3550Sstevel@tonic-gate  *	Tries to find the attrcache file for the given filegroup.
3560Sstevel@tonic-gate  *	If the file does not yet exist it is created.
3570Sstevel@tonic-gate  * Arguments:
3580Sstevel@tonic-gate  *	fgp	filegrp object
3590Sstevel@tonic-gate  * Returns:
3600Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
3610Sstevel@tonic-gate  * Preconditions:
3620Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
3630Sstevel@tonic-gate  */
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate int
filegrp_allocattr(filegrp_t * fgp)3660Sstevel@tonic-gate filegrp_allocattr(filegrp_t *fgp)
3670Sstevel@tonic-gate {
3680Sstevel@tonic-gate 	int error = 0;
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	/* if we do not yet have the attrcache file */
3730Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
3740Sstevel@tonic-gate 		/* fail if we tried to create it but failed previously */
3750Sstevel@tonic-gate 		if (fgp->fg_flags & CFS_FG_NOCACHE) {
3760Sstevel@tonic-gate 			error = ENOENT;
3770Sstevel@tonic-gate 			goto out;
3780Sstevel@tonic-gate 		}
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 		/* fail if we cannot read from the cache */
3810Sstevel@tonic-gate 		if ((fgp->fg_flags & CFS_FG_READ) == 0) {
3820Sstevel@tonic-gate 			error = ENOENT;
3830Sstevel@tonic-gate 			goto out;
3840Sstevel@tonic-gate 		}
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 		/* try to find the attrcache file in the cache */
3870Sstevel@tonic-gate 		error = filegrpattr_find(fgp);
3880Sstevel@tonic-gate 		if (error == ENOENT) {
3890Sstevel@tonic-gate 			/* fail if we cannot create the attrcache file */
3900Sstevel@tonic-gate 			if ((fgp->fg_flags & CFS_FG_WRITE) == 0) {
3910Sstevel@tonic-gate 				error = ENOENT;
3920Sstevel@tonic-gate 				goto out;
3930Sstevel@tonic-gate 			}
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate 			/* try to create the attrcache file */
3960Sstevel@tonic-gate 			error = filegrpattr_create(fgp);
3970Sstevel@tonic-gate 		}
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate out:
4000Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	return (error);
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate  * ------------------------------------------------------------------
4070Sstevel@tonic-gate  *
4080Sstevel@tonic-gate  *		filegrp_hold
4090Sstevel@tonic-gate  *
4100Sstevel@tonic-gate  * Description:
4110Sstevel@tonic-gate  *	Increments the number of references to this filegrp object.
4120Sstevel@tonic-gate  * Arguments:
4130Sstevel@tonic-gate  *	fgp	filegrp object to reference
4140Sstevel@tonic-gate  * Returns:
4150Sstevel@tonic-gate  * Preconditions:
4160Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
4170Sstevel@tonic-gate  */
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate void
filegrp_hold(filegrp_t * fgp)4200Sstevel@tonic-gate filegrp_hold(filegrp_t *fgp)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	fgp->fg_count++;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	/* remove attrcache file from the rl list if necessary */
4270Sstevel@tonic-gate 	if ((fgp->fg_flags & CFS_FG_WRITE) &&
4280Sstevel@tonic-gate 	    (fgp->fg_header != NULL) &&
4290Sstevel@tonic-gate 	    (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) {
4300Sstevel@tonic-gate #ifdef CFSDEBUG
4310Sstevel@tonic-gate 		cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
4320Sstevel@tonic-gate 		    CACHEFS_RL_GC, fgp->fg_header->ach_rlno);
4330Sstevel@tonic-gate #endif /* CFSDEBUG */
4340Sstevel@tonic-gate 		cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
4350Sstevel@tonic-gate 		    CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno,
4360Sstevel@tonic-gate 		    fgp->fg_header->ach_nblks);
4370Sstevel@tonic-gate 		fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE;
4380Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_UPDATED;
4390Sstevel@tonic-gate 	}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate  * ------------------------------------------------------------------
4460Sstevel@tonic-gate  *
4470Sstevel@tonic-gate  *		filegrp_rele
4480Sstevel@tonic-gate  *
4490Sstevel@tonic-gate  * Description:
4500Sstevel@tonic-gate  *	Decrements the number of references to this filegrp object.
4510Sstevel@tonic-gate  * Arguments:
4520Sstevel@tonic-gate  *	fgp	filegrp object to dereference
4530Sstevel@tonic-gate  * Returns:
4540Sstevel@tonic-gate  * Preconditions:
4550Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
456*5331Samw  *	precond(number of references to filegrp is > 0)
4570Sstevel@tonic-gate  */
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate void
filegrp_rele(filegrp_t * fgp)4600Sstevel@tonic-gate filegrp_rele(filegrp_t *fgp)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
4630Sstevel@tonic-gate 	ASSERT(fgp->fg_count > 0);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	/* move attrcache file to the rl list if necessary */
4660Sstevel@tonic-gate 	if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
4670Sstevel@tonic-gate 	    (fgp->fg_flags & CFS_FG_WRITE) &&
4680Sstevel@tonic-gate 	    (fgp->fg_header->ach_rl_current != CACHEFS_RL_GC) &&
4690Sstevel@tonic-gate 	    (fgp->fg_count == 1) &&
4700Sstevel@tonic-gate 	    (fgp->fg_header->ach_nffs == 0)) {
4710Sstevel@tonic-gate #ifdef CFSDEBUG
4720Sstevel@tonic-gate 		cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
4730Sstevel@tonic-gate 		    CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
4740Sstevel@tonic-gate #endif /* CFSDEBUG */
4750Sstevel@tonic-gate 		cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
4760Sstevel@tonic-gate 		    CACHEFS_RL_GC, fgp->fg_header->ach_rlno,
4770Sstevel@tonic-gate 		    fgp->fg_header->ach_nblks);
4780Sstevel@tonic-gate 		fgp->fg_header->ach_rl_current = CACHEFS_RL_GC;
4790Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_UPDATED;
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	fgp->fg_count--;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate }
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate /*
4890Sstevel@tonic-gate  * ------------------------------------------------------------------
4900Sstevel@tonic-gate  *
4910Sstevel@tonic-gate  *		filegrp_ffhold
4920Sstevel@tonic-gate  *
4930Sstevel@tonic-gate  * Description:
4940Sstevel@tonic-gate  *	Increments the count of the number of front files for
4950Sstevel@tonic-gate  *	this filegrp by one.
4960Sstevel@tonic-gate  * Arguments:
4970Sstevel@tonic-gate  *	fgp	filegrp object to reference
4980Sstevel@tonic-gate  * Returns:
4990Sstevel@tonic-gate  *	Returns 0 for success or a non-zero errno.
5000Sstevel@tonic-gate  * Preconditions:
5010Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
502*5331Samw  *	precond(number of references to filegrp is > 0)
5030Sstevel@tonic-gate  *	precond(filegrp is writable)
5040Sstevel@tonic-gate  */
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate int
filegrp_ffhold(filegrp_t * fgp)5070Sstevel@tonic-gate filegrp_ffhold(filegrp_t *fgp)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate 	int error = 0;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
5140Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_WRITE);
5150Sstevel@tonic-gate 	ASSERT(fgp->fg_count > 0);
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	/* if the filegrp is no good, bail out with warning */
5180Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_NOCACHE) {
5190Sstevel@tonic-gate 		error = EINVAL;
5200Sstevel@tonic-gate 		goto out;
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	/* if we do not have the directory vp yet */
5240Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_FILE) {
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 		/* create the directory if necessary */
5270Sstevel@tonic-gate 		if (fgp->fg_header->ach_nffs == 0) {
5280Sstevel@tonic-gate 			error = filegrpdir_create(fgp);
5290Sstevel@tonic-gate 			if (error)
5300Sstevel@tonic-gate 				goto out;
5310Sstevel@tonic-gate 		}
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 		/* else find the directory */
5340Sstevel@tonic-gate 		else {
5350Sstevel@tonic-gate 			error = filegrpdir_find(fgp);
5360Sstevel@tonic-gate 			if (error) {
5370Sstevel@tonic-gate #ifdef CFSDEBUG
5380Sstevel@tonic-gate 				CFS_DEBUG(CFSDEBUG_FILEGRP)
5390Sstevel@tonic-gate 					printf("ffhold: no dir, errno %d, "
5400Sstevel@tonic-gate 					    "fileno %llx\n",
5410Sstevel@tonic-gate 				error, (u_longlong_t)fgp->fg_id.cid_fileno);
5420Sstevel@tonic-gate #endif
5430Sstevel@tonic-gate 				goto out;
5440Sstevel@tonic-gate 			}
5450Sstevel@tonic-gate 		}
5460Sstevel@tonic-gate 	}
5470Sstevel@tonic-gate 	ASSERT(fgp->fg_dirvp);
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate #ifdef CFSDEBUG
5500Sstevel@tonic-gate 	if (fgp->fg_header->ach_nffs == 0) {
5510Sstevel@tonic-gate 		ASSERT(fgp->fg_header->ach_rl_current == CACHEFS_RL_ATTRFILE);
5520Sstevel@tonic-gate 		cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
5530Sstevel@tonic-gate 		    CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 		/*
5560Sstevel@tonic-gate 		 * XXX sam: this used to remove from the active list,
5570Sstevel@tonic-gate 		 * and put on `NONE'.  now, we're on
5580Sstevel@tonic-gate 		 * CACHEFS_RL_ATTRFILE if either count or nffs is
5590Sstevel@tonic-gate 		 * nonzero; CACHEFS_RL_GC otherwise.  since we just
5600Sstevel@tonic-gate 		 * asserted that we're not on CACHEFS_RL_GC, there's
5610Sstevel@tonic-gate 		 * nothing more to do.  right?
5620Sstevel@tonic-gate 		 */
5630Sstevel@tonic-gate 	}
5640Sstevel@tonic-gate #endif /* CFSDEBUG */
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	fgp->fg_header->ach_nffs++;
5670Sstevel@tonic-gate 	fgp->fg_flags |= CFS_FG_UPDATED;
5680Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate out:
5710Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate 	return (error);
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate  * ------------------------------------------------------------------
5780Sstevel@tonic-gate  *
5790Sstevel@tonic-gate  *		filegrp_ffrele
5800Sstevel@tonic-gate  *
5810Sstevel@tonic-gate  * Description:
5820Sstevel@tonic-gate  *	Decrements the count of the number of front files for
5830Sstevel@tonic-gate  *	this filegrp by one.
5840Sstevel@tonic-gate  * Arguments:
5850Sstevel@tonic-gate  *	fgp	filegrp object to dereference
5860Sstevel@tonic-gate  * Returns:
5870Sstevel@tonic-gate  * Preconditions:
5880Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
5890Sstevel@tonic-gate  *	precond(filegrp is writable)
590*5331Samw  *	precond(number of references to filegrp is > 0)
5910Sstevel@tonic-gate  *	precond(number of front file references is > 0)
5920Sstevel@tonic-gate  */
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate void
filegrp_ffrele(filegrp_t * fgp)5950Sstevel@tonic-gate filegrp_ffrele(filegrp_t *fgp)
5960Sstevel@tonic-gate {
5970Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
5980Sstevel@tonic-gate 	char *fname;
5990Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
6000Sstevel@tonic-gate 	int error = 0;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	/* if the filegrp is corrupt, bail out with warning */
6030Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_NOCACHE) {
6040Sstevel@tonic-gate 		return;
6050Sstevel@tonic-gate 	}
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
6100Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_WRITE);
6110Sstevel@tonic-gate 	ASSERT((fgp->fg_flags & CFS_FG_ALLOC_FILE) == 0);
6120Sstevel@tonic-gate 	ASSERT(fgp->fg_dirvp != NULL);
6130Sstevel@tonic-gate 	ASSERT(fgp->fg_count > 0);
6140Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs > 0);
6150Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	fgp->fg_header->ach_nffs--;
6180Sstevel@tonic-gate 	fgp->fg_flags |= CFS_FG_UPDATED;
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	if (fgp->fg_header->ach_nffs == 0) {
6210Sstevel@tonic-gate 		make_ascii_name(&fgp->fg_id, name);
6220Sstevel@tonic-gate 		fname = name;
6230Sstevel@tonic-gate 		error = VOP_RMDIR(fscp->fs_fscdirvp, fname,
624*5331Samw 		    fscp->fs_fscdirvp, kcred, NULL, 0);
6250Sstevel@tonic-gate 		if (error == 0) {
6260Sstevel@tonic-gate 			cachefs_freefile(fscp->fs_cache);
6270Sstevel@tonic-gate 			cachefs_freeblocks(fscp->fs_cache, 1,
6280Sstevel@tonic-gate 			    fgp->fg_header->ach_rl_current);
6290Sstevel@tonic-gate 			VN_RELE(fgp->fg_dirvp);
6300Sstevel@tonic-gate 			fgp->fg_dirvp = NULL;
6310Sstevel@tonic-gate 			fgp->fg_flags |= CFS_FG_ALLOC_FILE;
6320Sstevel@tonic-gate 		} else {
6330Sstevel@tonic-gate 			fgp->fg_flags |= CFS_FG_NOCACHE;
6340Sstevel@tonic-gate 			cmn_err(CE_WARN, "cachefs_ffrele:"
6350Sstevel@tonic-gate 			    " frontfs cache error %d, run fsck", error);
6360Sstevel@tonic-gate 		}
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 		/*
6390Sstevel@tonic-gate 		 * XXX sam: this used to move from `NONE' to
6400Sstevel@tonic-gate 		 * `CACHEFS_RL_ACTIVE'.  now, we're on
6410Sstevel@tonic-gate 		 * CACHEFS_RL_ATTRFILE if count and/or nffs is
6420Sstevel@tonic-gate 		 * nonzero, and CACHEFS_RL_GC otherwise.  since we
6430Sstevel@tonic-gate 		 * just asserted that count > 0, there's nothing to
6440Sstevel@tonic-gate 		 * do.  right?
6450Sstevel@tonic-gate 		 */
6460Sstevel@tonic-gate #ifdef CFSDEBUG
6470Sstevel@tonic-gate 		cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
6480Sstevel@tonic-gate 		    CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno);
6490Sstevel@tonic-gate #endif /* CFSDEBUG */
6500Sstevel@tonic-gate 	}
6510Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
6520Sstevel@tonic-gate }
6530Sstevel@tonic-gate 
6540Sstevel@tonic-gate /*
6550Sstevel@tonic-gate  * ------------------------------------------------------------------
6560Sstevel@tonic-gate  *
6570Sstevel@tonic-gate  *		filegrp_sync
6580Sstevel@tonic-gate  *
6590Sstevel@tonic-gate  * Description:
6600Sstevel@tonic-gate  *	Writes the file group's attrcache header to the attrcache
6610Sstevel@tonic-gate  *	file if necessary and syncs it.
6620Sstevel@tonic-gate  * Arguments:
6630Sstevel@tonic-gate  *	fgp	filegrp object
6640Sstevel@tonic-gate  * Returns:
6650Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
6660Sstevel@tonic-gate  * Preconditions:
6670Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
6680Sstevel@tonic-gate  */
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate int
filegrp_sync(filegrp_t * fgp)6710Sstevel@tonic-gate filegrp_sync(filegrp_t *fgp)
6720Sstevel@tonic-gate {
6730Sstevel@tonic-gate 	int error = 0;
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate 	if (((fgp->fg_flags & CFS_FG_UPDATED) == 0) ||
6780Sstevel@tonic-gate 	    (fgp->fg_flags & CFS_FG_ALLOC_ATTR) ||
6790Sstevel@tonic-gate 		CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp)) {
6800Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
6810Sstevel@tonic-gate 		return (0);
6820Sstevel@tonic-gate 	}
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)fgp->fg_header,
6870Sstevel@tonic-gate 	    fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
6880Sstevel@tonic-gate 	    kcred, NULL);
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	if (error == 0)
691*5331Samw 		error = VOP_FSYNC(fgp->fg_attrvp, FSYNC, kcred, NULL);
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	if (error == 0)
6940Sstevel@tonic-gate 		fgp->fg_flags &= ~CFS_FG_UPDATED;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 	return (error);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  * ------------------------------------------------------------------
7030Sstevel@tonic-gate  *
7040Sstevel@tonic-gate  *		filegrp_read_metadata
7050Sstevel@tonic-gate  *
7060Sstevel@tonic-gate  * Description:
7070Sstevel@tonic-gate  *	Reads the metadata for the specified file from the attrcache
7080Sstevel@tonic-gate  *	file belonging to the filegrp object.  Note that the md_rltype
7090Sstevel@tonic-gate  *	field may be incorrect if (cachep->c_flags & CACHE_CHECK_RLTYPE);
7100Sstevel@tonic-gate  *	in this case, if you care about md_rltype, you should double-check
7110Sstevel@tonic-gate  *	if rl_type is CACHEFS_RL_ACTIVE; cachefs_move_active_to_rl may have
7120Sstevel@tonic-gate  *	moved it without telling us.
7130Sstevel@tonic-gate  * Arguments:
7140Sstevel@tonic-gate  *	fgp	filegrp object
7150Sstevel@tonic-gate  *	cidp	the file to search for
7160Sstevel@tonic-gate  *	mdp	set to the metadata for the fileno
7170Sstevel@tonic-gate  * Returns:
7180Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
7190Sstevel@tonic-gate  * Preconditions:
7200Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
7210Sstevel@tonic-gate  *	precond(mdp)
7220Sstevel@tonic-gate  *	precond(slotp)
7230Sstevel@tonic-gate  */
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate int
filegrp_read_metadata(filegrp_t * fgp,cfs_cid_t * cidp,struct cachefs_metadata * mdp)7260Sstevel@tonic-gate filegrp_read_metadata(filegrp_t *fgp, cfs_cid_t *cidp,
7270Sstevel@tonic-gate     struct cachefs_metadata *mdp)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 	int slot;
7300Sstevel@tonic-gate 	int error;
7310Sstevel@tonic-gate 	int index;
7320Sstevel@tonic-gate 	struct cfs_cachefs_metadata	*tmpmdp;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 	ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
7370Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
7380Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
7390Sstevel@tonic-gate 		return (ENOENT);
7400Sstevel@tonic-gate 	}
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	slot = filegrp_cid_to_slot(fgp, cidp);
7430Sstevel@tonic-gate 	if (slot == 0) {
7440Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
7450Sstevel@tonic-gate 		return (ENOENT);
7460Sstevel@tonic-gate 	}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 
7490Sstevel@tonic-gate 	/* see if metadata was ever written */
750*5331Samw 	index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
7510Sstevel@tonic-gate 	if (fgp->fg_offsets[index].ach_written == 0) {
7520Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
7530Sstevel@tonic-gate 		return (ENOENT);
7540Sstevel@tonic-gate 	}
7550Sstevel@tonic-gate 
7560Sstevel@tonic-gate 	CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp);
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	error = vn_rdwr(UIO_READ, fgp->fg_attrvp,
7590Sstevel@tonic-gate 	    (caddr_t)tmpmdp, sizeof (struct cfs_cachefs_metadata),
7600Sstevel@tonic-gate 	    (offset_t)slot,
7614356Scasper 	    UIO_SYSSPACE, 0, (long long)0, kcred, NULL);
7620Sstevel@tonic-gate 	if (error) {
7630Sstevel@tonic-gate 		cmn_err(CE_WARN,
7640Sstevel@tonic-gate 		    "cachefs_read_metadata:"
7650Sstevel@tonic-gate 		    " frontfs cache error %d, run fsck", error);
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate 	CACHEFS_COPY_CFS_METADATA_TO_METADATA(tmpmdp, mdp);
7680Sstevel@tonic-gate 	CACHEFS_FREE_CFS_METADATA(tmpmdp);
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
7710Sstevel@tonic-gate 	return (error);
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate /*
7750Sstevel@tonic-gate  * ------------------------------------------------------------------
7760Sstevel@tonic-gate  *
7770Sstevel@tonic-gate  *		filegrp_create_metadata
7780Sstevel@tonic-gate  *
7790Sstevel@tonic-gate  * Description:
7800Sstevel@tonic-gate  *	Allocates a slot for the specified fileno.
7810Sstevel@tonic-gate  * Arguments:
7820Sstevel@tonic-gate  *	fgp	filegrp object
7830Sstevel@tonic-gate  *	cidp	the file to allocate a slot for
7840Sstevel@tonic-gate  * Returns:
7850Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
7860Sstevel@tonic-gate  * Preconditions:
7870Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
7880Sstevel@tonic-gate  */
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate int
filegrp_create_metadata(filegrp_t * fgp,struct cachefs_metadata * md,cfs_cid_t * cidp)7910Sstevel@tonic-gate filegrp_create_metadata(filegrp_t *fgp, struct cachefs_metadata *md,
7920Sstevel@tonic-gate     cfs_cid_t *cidp)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
7950Sstevel@tonic-gate 	cachefscache_t *cachep = fscp->fs_cache;
7960Sstevel@tonic-gate 	int slot;
7970Sstevel@tonic-gate 	int bitno;
798*5331Samw 	uchar_t mask;
7990Sstevel@tonic-gate 	int last;
8000Sstevel@tonic-gate 	int xx;
8010Sstevel@tonic-gate 	int index;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 	ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 	cachefs_cache_dirty(cachep, 1);
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
8100Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
8110Sstevel@tonic-gate 		return (ENOENT);
8120Sstevel@tonic-gate 	}
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	slot = filegrp_cid_to_slot(fgp, cidp);
8150Sstevel@tonic-gate 	if (slot) {
8160Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
8170Sstevel@tonic-gate 		return (0);
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
820*5331Samw 	index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 	ASSERT(index < fgp->fg_fscp->fs_info.fi_fgsize);
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	last = (((fgp->fg_fscp->fs_info.fi_fgsize + 7) & ~(7)) / 8);
8250Sstevel@tonic-gate 	for (xx = 0; xx < last; xx++) {
826*5331Samw 		if (fgp->fg_alloclist[xx] != (uchar_t)0xff) {
8270Sstevel@tonic-gate 			for (mask = 1, bitno = 0; bitno < 8; bitno++) {
8280Sstevel@tonic-gate 				if ((mask & fgp->fg_alloclist[xx]) == 0) {
8290Sstevel@tonic-gate 					slot = (xx * 8) + bitno;
8300Sstevel@tonic-gate 					goto found;
8310Sstevel@tonic-gate 				}
8320Sstevel@tonic-gate 				mask <<= 1;
8330Sstevel@tonic-gate 			}
8340Sstevel@tonic-gate 		}
8350Sstevel@tonic-gate 	}
8360Sstevel@tonic-gate found:
8370Sstevel@tonic-gate 	if (xx == last) {
8380Sstevel@tonic-gate 		cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
8390Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
8400Sstevel@tonic-gate 		return (ENOMEM);
8410Sstevel@tonic-gate 	}
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	slot = (slot * (int)sizeof (struct cfs_cachefs_metadata)) +
8440Sstevel@tonic-gate 		fgp->fg_headersize;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
8470Sstevel@tonic-gate 	fgp->fg_header->ach_count++;
8480Sstevel@tonic-gate 	fgp->fg_offsets[index].ach_offset = slot;
8490Sstevel@tonic-gate 	fgp->fg_offsets[index].ach_written = 0;
8500Sstevel@tonic-gate 	fgp->fg_alloclist[xx] |= mask;
8510Sstevel@tonic-gate 	fgp->fg_flags |= CFS_FG_UPDATED;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_MDCREATE))
8560Sstevel@tonic-gate 		cachefs_log_mdcreate(cachep, 0,
8570Sstevel@tonic-gate 		    fscp->fs_cfsvfsp, &md->md_cookie, cidp->cid_fileno,
8580Sstevel@tonic-gate 		    fgp->fg_header->ach_count);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	return (0);
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate /*
8640Sstevel@tonic-gate  * ------------------------------------------------------------------
8650Sstevel@tonic-gate  *
8660Sstevel@tonic-gate  *		filegrp_write_metadata
8670Sstevel@tonic-gate  *
8680Sstevel@tonic-gate  * Description:
8690Sstevel@tonic-gate  *	Writes metadata to the slot held by file.
8700Sstevel@tonic-gate  * Arguments:
8710Sstevel@tonic-gate  *	fgp	filegrp object
8720Sstevel@tonic-gate  *	cidp	the file to write the metadata for
8730Sstevel@tonic-gate  *	mdp	the metadata to write
8740Sstevel@tonic-gate  * Returns:
8750Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
8760Sstevel@tonic-gate  * Preconditions:
8770Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
8780Sstevel@tonic-gate  *	precond(mdp)
8790Sstevel@tonic-gate  */
8800Sstevel@tonic-gate int
filegrp_write_metadata(filegrp_t * fgp,cfs_cid_t * cidp,struct cachefs_metadata * mdp)8810Sstevel@tonic-gate filegrp_write_metadata(filegrp_t *fgp, cfs_cid_t *cidp,
8820Sstevel@tonic-gate     struct cachefs_metadata *mdp)
8830Sstevel@tonic-gate {
8840Sstevel@tonic-gate 	int error = 0;
8850Sstevel@tonic-gate 	int slot;
8860Sstevel@tonic-gate 	blkcnt64_t nblks;
8870Sstevel@tonic-gate 	int index;
8880Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
8890Sstevel@tonic-gate 	struct cfs_cachefs_metadata	*tmpmdp;
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	cachefs_cache_dirty(fscp->fs_cache, 1);
8940Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
8970Sstevel@tonic-gate 		error = ENOENT;
8980Sstevel@tonic-gate 		goto out;
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	slot = filegrp_cid_to_slot(fgp, cidp);
9020Sstevel@tonic-gate 	if (slot == 0) {
9030Sstevel@tonic-gate 		error = ENOENT;
9040Sstevel@tonic-gate 		goto out;
9050Sstevel@tonic-gate 	}
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 	/* allocate blocks for the data if necessary */
9080Sstevel@tonic-gate 	nblks = slot + sizeof (struct cfs_cachefs_metadata);
9090Sstevel@tonic-gate 	nblks = (nblks + MAXBSIZE - 1) / MAXBSIZE;
9100Sstevel@tonic-gate 	nblks -= fgp->fg_header->ach_nblks;
9110Sstevel@tonic-gate 	if (nblks > 0) {
9120Sstevel@tonic-gate 		error = cachefs_allocblocks(fscp->fs_cache, nblks,
9130Sstevel@tonic-gate 		    fgp->fg_header->ach_rl_current);
9140Sstevel@tonic-gate 		if (error)
9150Sstevel@tonic-gate 			goto out;
9160Sstevel@tonic-gate 		error = filegrp_write_space(fgp->fg_attrvp,
9170Sstevel@tonic-gate 			(offset_t)fgp->fg_header->ach_nblks * MAXBSIZE,
9180Sstevel@tonic-gate 			nblks * MAXBSIZE);
9190Sstevel@tonic-gate 		if (error) {
9200Sstevel@tonic-gate 			cachefs_freeblocks(fscp->fs_cache, nblks,
9210Sstevel@tonic-gate 			    fgp->fg_header->ach_rl_current);
9220Sstevel@tonic-gate 			goto out;
9230Sstevel@tonic-gate 		}
9240Sstevel@tonic-gate 	} else
9250Sstevel@tonic-gate 		nblks = 0;
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 	CACHEFS_ALLOC_CFS_METADATA(tmpmdp, mdp);
9280Sstevel@tonic-gate 	CACHEFS_COPY_METADATA_TO_CFS_METADATA(mdp, tmpmdp, error);
9290Sstevel@tonic-gate 	/* write the metadata */
9300Sstevel@tonic-gate 	if (!error)
9310Sstevel@tonic-gate 		error = vn_rdwr(UIO_WRITE, fgp->fg_attrvp, (caddr_t)tmpmdp,
9320Sstevel@tonic-gate 			sizeof (struct cfs_cachefs_metadata), (offset_t)slot,
9330Sstevel@tonic-gate 			UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	CACHEFS_FREE_CFS_METADATA(tmpmdp);
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	if (error) {
9380Sstevel@tonic-gate 		if (error == EOVERFLOW) {
9390Sstevel@tonic-gate 			cmn_err(CE_WARN, "cachefs_write_metadata:"
9400Sstevel@tonic-gate 			    " time/dev overflow error %d", error);
9410Sstevel@tonic-gate 		} else if (error != ENOSPC) {
9420Sstevel@tonic-gate 			cmn_err(CE_WARN,
9430Sstevel@tonic-gate 			    "cachefs: UFS write error %d, run fsck",
9440Sstevel@tonic-gate 			    error);
9450Sstevel@tonic-gate 		}
9460Sstevel@tonic-gate 		cachefs_freeblocks(fscp->fs_cache, nblks,
9470Sstevel@tonic-gate 		    fgp->fg_header->ach_rl_current);
9480Sstevel@tonic-gate 		goto out;
9490Sstevel@tonic-gate 	}
9500Sstevel@tonic-gate 
9510Sstevel@tonic-gate 	/* mark metadata as having been written */
952*5331Samw 	index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
9530Sstevel@tonic-gate 	fgp->fg_offsets[index].ach_written = 1;
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	/* update number of blocks used by the attrcache file */
9560Sstevel@tonic-gate 	fgp->fg_header->ach_nblks += nblks;
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	/* force sync to be done eventually */
9590Sstevel@tonic-gate 	fgp->fg_flags |= CFS_FG_UPDATED;
9600Sstevel@tonic-gate 
9610Sstevel@tonic-gate out:
9620Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
9630Sstevel@tonic-gate 	return (error);
9640Sstevel@tonic-gate }
9650Sstevel@tonic-gate 
9660Sstevel@tonic-gate /*
9670Sstevel@tonic-gate  * ------------------------------------------------------------------
9680Sstevel@tonic-gate  *
9690Sstevel@tonic-gate  *		filegrp_destroy_metadata
9700Sstevel@tonic-gate  *
9710Sstevel@tonic-gate  * Description:
9720Sstevel@tonic-gate  *	Destroys the metadata associated with the specified file.
9730Sstevel@tonic-gate  * Arguments:
9740Sstevel@tonic-gate  *	fgp	filegrp object
9750Sstevel@tonic-gate  *	cidp	the file to destroy the metadata for
9760Sstevel@tonic-gate  * Returns:
9770Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
9780Sstevel@tonic-gate  * Preconditions:
9790Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
9800Sstevel@tonic-gate  */
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate int
filegrp_destroy_metadata(filegrp_t * fgp,cfs_cid_t * cidp)9830Sstevel@tonic-gate filegrp_destroy_metadata(filegrp_t *fgp, cfs_cid_t *cidp)
9840Sstevel@tonic-gate {
9850Sstevel@tonic-gate 	int i;
9860Sstevel@tonic-gate 	int bitno;
987*5331Samw 	uchar_t mask = 1;
9880Sstevel@tonic-gate 
9890Sstevel@tonic-gate 	int slot;
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	ASSERT(CFS_ISFS_BACKFS_NFSV4(fgp->fg_fscp) == 0);
9920Sstevel@tonic-gate 
9930Sstevel@tonic-gate 	cachefs_cache_dirty(fgp->fg_fscp->fs_cache, 1);
9940Sstevel@tonic-gate 	mutex_enter(&fgp->fg_mutex);
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR) {
9970Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
9980Sstevel@tonic-gate 		return (ENOENT);
9990Sstevel@tonic-gate 	}
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	slot = filegrp_cid_to_slot(fgp, cidp);
10020Sstevel@tonic-gate 	if (slot == 0) {
10030Sstevel@tonic-gate 		mutex_exit(&fgp->fg_mutex);
10040Sstevel@tonic-gate 		return (ENOENT);
10050Sstevel@tonic-gate 	}
10060Sstevel@tonic-gate 
10070Sstevel@tonic-gate 	i = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
10080Sstevel@tonic-gate 	fgp->fg_offsets[i].ach_offset = 0;
10090Sstevel@tonic-gate 	fgp->fg_offsets[i].ach_written = 0;
10100Sstevel@tonic-gate 	i = (slot - fgp->fg_headersize) /
10110Sstevel@tonic-gate 		(int)sizeof (struct cfs_cachefs_metadata);
10120Sstevel@tonic-gate 	bitno = i & 7;
10130Sstevel@tonic-gate 	i = i >> 3;
10140Sstevel@tonic-gate 	mask <<= bitno;
10150Sstevel@tonic-gate 	if (fgp->fg_alloclist[i] & mask)
10160Sstevel@tonic-gate 		fgp->fg_alloclist[i] &= ~mask;
10170Sstevel@tonic-gate 	else
10180Sstevel@tonic-gate 		cmn_err(CE_WARN,
10190Sstevel@tonic-gate 		    "filegrp_destroy_metadata:"
10200Sstevel@tonic-gate 		    " fileno %" PRId64 " slot %d-%d fgp %p not allocated",
10210Sstevel@tonic-gate 		    cidp->cid_fileno, i, bitno, (void *)fgp);
10220Sstevel@tonic-gate 
10230Sstevel@tonic-gate 	fgp->fg_header->ach_count--;
10240Sstevel@tonic-gate 	ASSERT(fgp->fg_header->ach_nffs <= fgp->fg_header->ach_count);
10250Sstevel@tonic-gate 	fgp->fg_flags |= CFS_FG_UPDATED;
10260Sstevel@tonic-gate 	mutex_exit(&fgp->fg_mutex);
10270Sstevel@tonic-gate 
10280Sstevel@tonic-gate 	return (0);
10290Sstevel@tonic-gate }
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate /*
10320Sstevel@tonic-gate  * ------------------------------------------------------------------
10330Sstevel@tonic-gate  *
10340Sstevel@tonic-gate  *		filegrp_list_find
10350Sstevel@tonic-gate  *
10360Sstevel@tonic-gate  * Description:
10370Sstevel@tonic-gate  *	Looks for the filegrp that owns the specified file
10380Sstevel@tonic-gate  *	on the fscp filegrp lists.
10390Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
10400Sstevel@tonic-gate  *	By convention the filegrp object returned may be used as
10410Sstevel@tonic-gate  *	long as the fs_fslock is held.  To use the filegrp after
10420Sstevel@tonic-gate  *	dropping fs_fslock, call filegrp_hold.
10430Sstevel@tonic-gate  * Arguments:
10440Sstevel@tonic-gate  *	fscp	fscache object
10450Sstevel@tonic-gate  *	cidp	the file to search on
10460Sstevel@tonic-gate  * Returns:
10470Sstevel@tonic-gate  *	Returns the filegrp object if found, NULL if not.
10480Sstevel@tonic-gate  * Preconditions:
10490Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
10500Sstevel@tonic-gate  */
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate filegrp_t *
filegrp_list_find(struct fscache * fscp,cfs_cid_t * cidp)10530Sstevel@tonic-gate filegrp_list_find(struct fscache *fscp, cfs_cid_t *cidp)
10540Sstevel@tonic-gate {
10550Sstevel@tonic-gate 	int fgsize = fscp->fs_info.fi_fgsize;
10560Sstevel@tonic-gate 	struct filegrp *fgp;
10570Sstevel@tonic-gate 	ino64_t fxx;
10580Sstevel@tonic-gate 	int findex;
10590Sstevel@tonic-gate 	ino64_t fileno;
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	/* get fileno of filegrp */
10640Sstevel@tonic-gate 	fxx = (ino64_t)(cidp->cid_fileno / fgsize);
10650Sstevel@tonic-gate 	fileno = fxx * fgsize;
10660Sstevel@tonic-gate 
10670Sstevel@tonic-gate 	/* hash into array of file groups */
1068*5331Samw 	findex = (int)(fxx & (CFS_FS_FGP_BUCKET_SIZE - 1));
10690Sstevel@tonic-gate 
10700Sstevel@tonic-gate 	/* search set of file groups for this hash bucket */
10710Sstevel@tonic-gate 	for (fgp = fscp->fs_filegrp[findex];
10720Sstevel@tonic-gate 	    fgp != NULL;
10730Sstevel@tonic-gate 	    fgp = fgp->fg_next) {
10740Sstevel@tonic-gate 		if ((fgp->fg_id.cid_fileno == fileno) &&
10750Sstevel@tonic-gate 		    (fgp->fg_id.cid_flags == cidp->cid_flags))
10760Sstevel@tonic-gate 			break;
10770Sstevel@tonic-gate 	}
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	return (fgp);
10800Sstevel@tonic-gate }
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate /*
10830Sstevel@tonic-gate  * ------------------------------------------------------------------
10840Sstevel@tonic-gate  *
10850Sstevel@tonic-gate  *		filegrp_list_add
10860Sstevel@tonic-gate  *
10870Sstevel@tonic-gate  * Description:
10880Sstevel@tonic-gate  *	Adds the filegrp to the list of filegrps in the fscp.
10890Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
10900Sstevel@tonic-gate  * Arguments:
10910Sstevel@tonic-gate  *	fscp	fscache object
10920Sstevel@tonic-gate  *	fgp	filegrp object
10930Sstevel@tonic-gate  * Returns:
10940Sstevel@tonic-gate  * Preconditions:
10950Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
10960Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
10970Sstevel@tonic-gate  *	precond(fgp is not already on a list of filegrps)
10980Sstevel@tonic-gate  */
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate void
filegrp_list_add(struct fscache * fscp,filegrp_t * fgp)11010Sstevel@tonic-gate filegrp_list_add(struct fscache *fscp, filegrp_t *fgp)
11020Sstevel@tonic-gate {
11030Sstevel@tonic-gate 	int findex;
11040Sstevel@tonic-gate 	int fgsize = fscp->fs_info.fi_fgsize;
11050Sstevel@tonic-gate 
11060Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
11070Sstevel@tonic-gate 	ASSERT(fgp->fg_next == NULL);
11080Sstevel@tonic-gate 
11090Sstevel@tonic-gate 	/* hash into array of file groups */
1110*5331Samw 	findex = (int)((fgp->fg_id.cid_fileno / fgsize) &
11110Sstevel@tonic-gate 	    (CFS_FS_FGP_BUCKET_SIZE - 1));
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	fgp->fg_next = fscp->fs_filegrp[findex];
11140Sstevel@tonic-gate 	fscp->fs_filegrp[findex] = fgp;
11150Sstevel@tonic-gate 	fscp->fs_ref++;
11160Sstevel@tonic-gate }
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate /*
11190Sstevel@tonic-gate  * ------------------------------------------------------------------
11200Sstevel@tonic-gate  *
11210Sstevel@tonic-gate  *		filegrp_list_remove
11220Sstevel@tonic-gate  *
11230Sstevel@tonic-gate  * Description:
11240Sstevel@tonic-gate  *	Removes the filegrp from the list of filegrps in the fscp.
11250Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
11260Sstevel@tonic-gate  * Arguments:
11270Sstevel@tonic-gate  *	fscp	fscache object
11280Sstevel@tonic-gate  *	fgp	filegrp object
11290Sstevel@tonic-gate  * Returns:
11300Sstevel@tonic-gate  * Preconditions:
11310Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
11320Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
11330Sstevel@tonic-gate  *	precond(fgp is on the list of filegrps in fscp)
11340Sstevel@tonic-gate  */
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate void
filegrp_list_remove(struct fscache * fscp,filegrp_t * fgp)11370Sstevel@tonic-gate filegrp_list_remove(struct fscache *fscp, filegrp_t *fgp)
11380Sstevel@tonic-gate {
11390Sstevel@tonic-gate 	struct filegrp *fp;
11400Sstevel@tonic-gate 	struct filegrp **pfgp;
11410Sstevel@tonic-gate 	int found = 0;
11420Sstevel@tonic-gate 	int findex;
11430Sstevel@tonic-gate 	int fgsize = fscp->fs_info.fi_fgsize;
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	/* hash into array of file groups */
1148*5331Samw 	findex = (int)((fgp->fg_id.cid_fileno / fgsize) &
11490Sstevel@tonic-gate 	    (CFS_FS_FGP_BUCKET_SIZE - 1));
11500Sstevel@tonic-gate 	fp = fscp->fs_filegrp[findex];
11510Sstevel@tonic-gate 	pfgp = &fscp->fs_filegrp[findex];
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 	while (fp != NULL) {
11540Sstevel@tonic-gate 		if (fp == fgp) {
11550Sstevel@tonic-gate 			*pfgp = fp->fg_next;
11560Sstevel@tonic-gate 			fp->fg_next = NULL;
11570Sstevel@tonic-gate 			found++;
11580Sstevel@tonic-gate 			break;
11590Sstevel@tonic-gate 		}
11600Sstevel@tonic-gate 		pfgp = &fp->fg_next;
11610Sstevel@tonic-gate 		fp = fp->fg_next;
11620Sstevel@tonic-gate 	}
11630Sstevel@tonic-gate 	ASSERT(found);
11640Sstevel@tonic-gate 	fscp->fs_ref--;
11650Sstevel@tonic-gate }
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate /*
11680Sstevel@tonic-gate  * ------------------------------------------------------------------
11690Sstevel@tonic-gate  *
11700Sstevel@tonic-gate  *		filegrp_list_gc
11710Sstevel@tonic-gate  *
11720Sstevel@tonic-gate  * Description:
11730Sstevel@tonic-gate  *	Traverses the filegrp lists and throws away any filegrps that are
11740Sstevel@tonic-gate  *	not in use.
11750Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
11760Sstevel@tonic-gate  * Arguments:
11770Sstevel@tonic-gate  *	fscp	fscache object
11780Sstevel@tonic-gate  * Returns:
11790Sstevel@tonic-gate  * Preconditions:
11800Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
11810Sstevel@tonic-gate  */
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate void
filegrp_list_gc(struct fscache * fscp)11840Sstevel@tonic-gate filegrp_list_gc(struct fscache *fscp)
11850Sstevel@tonic-gate {
11860Sstevel@tonic-gate 	struct filegrp *next, *fgp;
11870Sstevel@tonic-gate 	int xx;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
11920Sstevel@tonic-gate 		for (fgp = fscp->fs_filegrp[xx]; fgp != NULL; fgp = next) {
11930Sstevel@tonic-gate 			next = fgp->fg_next;
11940Sstevel@tonic-gate 			mutex_enter(&fgp->fg_mutex);
11950Sstevel@tonic-gate 			if (fgp->fg_count > 0) {
11960Sstevel@tonic-gate 				mutex_exit(&fgp->fg_mutex);
11970Sstevel@tonic-gate 				continue;
11980Sstevel@tonic-gate 			}
11990Sstevel@tonic-gate 			mutex_exit(&fgp->fg_mutex);
12000Sstevel@tonic-gate 			filegrp_list_remove(fscp, fgp);
12010Sstevel@tonic-gate 			filegrp_destroy(fgp);
12020Sstevel@tonic-gate 		}
12030Sstevel@tonic-gate 	}
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate 
12060Sstevel@tonic-gate /*
12070Sstevel@tonic-gate  * ------------------------------------------------------------------
12080Sstevel@tonic-gate  *
12090Sstevel@tonic-gate  *		filegrp_setup
12100Sstevel@tonic-gate  *
12110Sstevel@tonic-gate  * Description:
12120Sstevel@tonic-gate  *	Perform initialization actions on the given filegrp.
12130Sstevel@tonic-gate  *	The fgp->fg_mutex must be held while this routine is called.
12140Sstevel@tonic-gate  * Arguments:
12150Sstevel@tonic-gate  *	fgp	filegrp object
12160Sstevel@tonic-gate  *	flags	flags to be OR'ed into the fgp flags field
12170Sstevel@tonic-gate  *	dorl	indicates whether filegrp should be removed from rl or not
12180Sstevel@tonic-gate  * Returns:
12190Sstevel@tonic-gate  * Preconditions:
12200Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
12210Sstevel@tonic-gate  */
12220Sstevel@tonic-gate static void
filegrp_setup(struct filegrp * fgp,int flags,int dorl)12230Sstevel@tonic-gate filegrp_setup(struct filegrp *fgp, int flags, int dorl)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fgp->fg_mutex));
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	/* turn on the specified flags */
12280Sstevel@tonic-gate 	if (flags)
12290Sstevel@tonic-gate 		fgp->fg_flags |= flags;
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	/* if the attrcache file exists, find it */
12320Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR)
12330Sstevel@tonic-gate 		(void) filegrpattr_find(fgp);
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 	/* if the attrcache directory exists, find it */
12360Sstevel@tonic-gate 	if (((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
12370Sstevel@tonic-gate 	    (fgp->fg_flags & CFS_FG_ALLOC_FILE) &&
12380Sstevel@tonic-gate 	    (fgp->fg_header->ach_nffs > 0)) {
12390Sstevel@tonic-gate 		(void) filegrpdir_find(fgp);
12400Sstevel@tonic-gate 	}
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate 	/* move from gc list to attrfile list if necessary */
12430Sstevel@tonic-gate 	if ((dorl != 0) &&
12440Sstevel@tonic-gate 	    ((fgp->fg_flags & CFS_FG_ALLOC_ATTR) == 0) &&
12450Sstevel@tonic-gate 	    (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC)) {
12460Sstevel@tonic-gate 		ASSERT(fgp->fg_header->ach_nffs == 0);
12470Sstevel@tonic-gate 		if (fgp->fg_count > 0) {
12480Sstevel@tonic-gate #ifdef CFSDEBUG
12490Sstevel@tonic-gate 			cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
12500Sstevel@tonic-gate 			    CACHEFS_RL_GC, fgp->fg_header->ach_rlno);
12510Sstevel@tonic-gate #endif /* CFSDEBUG */
12520Sstevel@tonic-gate 			cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
12530Sstevel@tonic-gate 			    CACHEFS_RL_ATTRFILE, fgp->fg_header->ach_rlno,
12540Sstevel@tonic-gate 			    fgp->fg_header->ach_nblks);
12550Sstevel@tonic-gate 			fgp->fg_header->ach_rl_current = CACHEFS_RL_ATTRFILE;
12560Sstevel@tonic-gate 			fgp->fg_flags |= CFS_FG_UPDATED;
12570Sstevel@tonic-gate 		}
12580Sstevel@tonic-gate 	}
12590Sstevel@tonic-gate }
12600Sstevel@tonic-gate 
12610Sstevel@tonic-gate /*
12620Sstevel@tonic-gate  * ------------------------------------------------------------------
12630Sstevel@tonic-gate  *
12640Sstevel@tonic-gate  *		filegrp_list_enable_caching_ro
12650Sstevel@tonic-gate  *
12660Sstevel@tonic-gate  * Description:
12670Sstevel@tonic-gate  *	Traverses the filegrp lists and enables the
12680Sstevel@tonic-gate  *	use of the cache read-only.
12690Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
12700Sstevel@tonic-gate  * Arguments:
12710Sstevel@tonic-gate  *	fscp	fscache object
12720Sstevel@tonic-gate  * Returns:
12730Sstevel@tonic-gate  * Preconditions:
12740Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
12750Sstevel@tonic-gate  */
12760Sstevel@tonic-gate 
12770Sstevel@tonic-gate void
filegrp_list_enable_caching_ro(struct fscache * fscp)12780Sstevel@tonic-gate filegrp_list_enable_caching_ro(struct fscache *fscp)
12790Sstevel@tonic-gate {
12800Sstevel@tonic-gate 	struct filegrp *fgp;
12810Sstevel@tonic-gate 	int xx;
12820Sstevel@tonic-gate 
12830Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate 	for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
12860Sstevel@tonic-gate 		for (fgp = fscp->fs_filegrp[xx]; fgp != NULL;
12870Sstevel@tonic-gate 		    fgp = fgp->fg_next) {
12880Sstevel@tonic-gate 			mutex_enter(&fgp->fg_mutex);
12890Sstevel@tonic-gate 			filegrp_setup(fgp, 0, 0);
12900Sstevel@tonic-gate 			mutex_exit(&fgp->fg_mutex);
12910Sstevel@tonic-gate 		}
12920Sstevel@tonic-gate 	}
12930Sstevel@tonic-gate }
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate /*
12960Sstevel@tonic-gate  * ------------------------------------------------------------------
12970Sstevel@tonic-gate  *
12980Sstevel@tonic-gate  *		filegrp_list_enable_caching_rw
12990Sstevel@tonic-gate  *
13000Sstevel@tonic-gate  * Description:
13010Sstevel@tonic-gate  *	Traverses the filegrp lists and enables the
13020Sstevel@tonic-gate  *	use of the cache read-write.
13030Sstevel@tonic-gate  *	The fscp->fs_fslock must be held while this routine is called.
13040Sstevel@tonic-gate  * Arguments:
13050Sstevel@tonic-gate  *	fscp	fscache object
13060Sstevel@tonic-gate  * Returns:
13070Sstevel@tonic-gate  * Preconditions:
13080Sstevel@tonic-gate  *	precond(fscp is a valid fscache object)
13090Sstevel@tonic-gate  *	precond(all filegrps must be in the read-only state)
13100Sstevel@tonic-gate  */
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate void
filegrp_list_enable_caching_rw(struct fscache * fscp)13130Sstevel@tonic-gate filegrp_list_enable_caching_rw(struct fscache *fscp)
13140Sstevel@tonic-gate {
13150Sstevel@tonic-gate 	struct filegrp *fgp;
13160Sstevel@tonic-gate 	int xx;
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fscp->fs_fslock));
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 	for (xx = 0; xx < CFS_FS_FGP_BUCKET_SIZE; xx++) {
13210Sstevel@tonic-gate 		for (fgp = fscp->fs_filegrp[xx]; fgp != NULL;
13220Sstevel@tonic-gate 		    fgp = fgp->fg_next) {
13230Sstevel@tonic-gate 			mutex_enter(&fgp->fg_mutex);
13240Sstevel@tonic-gate 			filegrp_setup(fgp, CFS_FG_READ|CFS_FG_WRITE, 1);
13250Sstevel@tonic-gate 			mutex_exit(&fgp->fg_mutex);
13260Sstevel@tonic-gate 		}
13270Sstevel@tonic-gate 	}
13280Sstevel@tonic-gate }
13290Sstevel@tonic-gate 
13300Sstevel@tonic-gate /*
13310Sstevel@tonic-gate  * ------------------------------------------------------------------
13320Sstevel@tonic-gate  *
13330Sstevel@tonic-gate  *		filegrpdir_find
13340Sstevel@tonic-gate  *
13350Sstevel@tonic-gate  * Description:
13360Sstevel@tonic-gate  *	Tries to find the filegrp frontfile directory in the cache.
13370Sstevel@tonic-gate  *	If found CFS_FG_ALLOC_FILE is turned off.
13380Sstevel@tonic-gate  *	This routine should not be called if CFS_FG_ALLOC_FILE is
13390Sstevel@tonic-gate  *	already off.
13400Sstevel@tonic-gate  * Arguments:
13410Sstevel@tonic-gate  *	fgp	filegrp object
13420Sstevel@tonic-gate  * Returns:
13430Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
13440Sstevel@tonic-gate  * Preconditions:
13450Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
13460Sstevel@tonic-gate  */
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate int
filegrpdir_find(filegrp_t * fgp)13490Sstevel@tonic-gate filegrpdir_find(filegrp_t *fgp)
13500Sstevel@tonic-gate {
13510Sstevel@tonic-gate 	int error;
13520Sstevel@tonic-gate 	vnode_t *dirvp;
13530Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
13540Sstevel@tonic-gate 	char *fname;
13550Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_ALLOC_ATTR)
13580Sstevel@tonic-gate 		return (ENOENT);
13590Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_ALLOC_FILE);
13600Sstevel@tonic-gate 
13610Sstevel@tonic-gate 	make_ascii_name(&fgp->fg_id, name);
13620Sstevel@tonic-gate 	fname = name;
13630Sstevel@tonic-gate 	error = VOP_LOOKUP(fscp->fs_fscdirvp, fname, &dirvp, NULL,
1364*5331Samw 			0, NULL, kcred, NULL, NULL, NULL);
13650Sstevel@tonic-gate 	if (error == 0) {
13660Sstevel@tonic-gate 		fgp->fg_dirvp = dirvp;
13670Sstevel@tonic-gate 		fgp->fg_flags &= ~CFS_FG_ALLOC_FILE;
13680Sstevel@tonic-gate #ifdef CFSDEBUG
13690Sstevel@tonic-gate 		if (fgp->fg_header->ach_nffs == 0) {
13700Sstevel@tonic-gate 			CFS_DEBUG(CFSDEBUG_FILEGRP)
13710Sstevel@tonic-gate 				printf("filegrpdir_find: "
13720Sstevel@tonic-gate 				    "%s found but no front files\n", fname);
13730Sstevel@tonic-gate 		}
13740Sstevel@tonic-gate #endif
13750Sstevel@tonic-gate 	}
13760Sstevel@tonic-gate #ifdef CFSDEBUG
13770Sstevel@tonic-gate 	else if (fgp->fg_header->ach_nffs != 0) {
13780Sstevel@tonic-gate 		CFS_DEBUG(CFSDEBUG_FILEGRP)
13790Sstevel@tonic-gate 			printf("filegrpdir_find: "
13800Sstevel@tonic-gate 				"%s NOT found but %d front files\n",
13810Sstevel@tonic-gate 				fname, fgp->fg_header->ach_nffs);
13820Sstevel@tonic-gate 	}
13830Sstevel@tonic-gate #endif
13840Sstevel@tonic-gate 	return (error);
13850Sstevel@tonic-gate }
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate /*
13880Sstevel@tonic-gate  * ------------------------------------------------------------------
13890Sstevel@tonic-gate  *
13900Sstevel@tonic-gate  *		filegrparttr_find
13910Sstevel@tonic-gate  *
13920Sstevel@tonic-gate  * Description:
13930Sstevel@tonic-gate  *	Tries to find the attrcache file for the given filegrp.
13940Sstevel@tonic-gate  *	If found the header information is read in and
13950Sstevel@tonic-gate  *	CFS_FG_ALLOC_ATTR is turned off.
13960Sstevel@tonic-gate  *	This routine should not be called if CFS_FG_ALLOC_ATTR is
13970Sstevel@tonic-gate  *	already off.
13980Sstevel@tonic-gate  * Arguments:
13990Sstevel@tonic-gate  *	fgp	filegrp object
14000Sstevel@tonic-gate  * Returns:
14010Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
14020Sstevel@tonic-gate  * Preconditions:
14030Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
14040Sstevel@tonic-gate  *	precond(fgp is readable)
14050Sstevel@tonic-gate  */
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate int
filegrpattr_find(struct filegrp * fgp)14080Sstevel@tonic-gate filegrpattr_find(struct filegrp *fgp)
14090Sstevel@tonic-gate {
14100Sstevel@tonic-gate 	int error = 0;
14110Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
14120Sstevel@tonic-gate 	cachefscache_t *cachep = fscp->fs_cache;
14130Sstevel@tonic-gate 	vnode_t *attrvp;
14140Sstevel@tonic-gate 	struct attrcache_header *ahp;
14150Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
14160Sstevel@tonic-gate 	char *fname;
14170Sstevel@tonic-gate 
14180Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_NOCACHE)
14190Sstevel@tonic-gate 		return (ENOENT);
14200Sstevel@tonic-gate 
14210Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_ALLOC_ATTR);
14220Sstevel@tonic-gate 	make_ascii_name(&fgp->fg_id, name);
14230Sstevel@tonic-gate 	fname = name;
14240Sstevel@tonic-gate 	error = VOP_LOOKUP(fscp->fs_fsattrdir, fname,
1425*5331Samw 	    &attrvp, NULL, 0, NULL, kcred, NULL, NULL, NULL);
14260Sstevel@tonic-gate 	if (error) {
14270Sstevel@tonic-gate 		return (error);
14280Sstevel@tonic-gate 	}
14290Sstevel@tonic-gate 	ahp = (struct attrcache_header *)cachefs_kmem_zalloc(
14300Sstevel@tonic-gate 	    fgp->fg_headersize, KM_SLEEP);
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 	error = vn_rdwr(UIO_READ, attrvp, (caddr_t)ahp,
14330Sstevel@tonic-gate 				fgp->fg_headersize, 0LL, UIO_SYSSPACE,
14344356Scasper 			0, (rlim64_t)RLIM_INFINITY, kcred, NULL);
14350Sstevel@tonic-gate 	if (error) {
14360Sstevel@tonic-gate 		cmn_err(CE_WARN, "cachefs: Read attrcache error %d, run fsck",
14370Sstevel@tonic-gate 		    error);
14380Sstevel@tonic-gate 		cachefs_kmem_free(ahp, fgp->fg_headersize);
14390Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_NOCACHE;
14400Sstevel@tonic-gate 		VN_RELE(attrvp);
14410Sstevel@tonic-gate 	} else {
14420Sstevel@tonic-gate 		ASSERT(ahp->ach_nffs <= ahp->ach_count);
14430Sstevel@tonic-gate 		fgp->fg_attrvp = attrvp;
14440Sstevel@tonic-gate 		fgp->fg_header = ahp;
14450Sstevel@tonic-gate 		fgp->fg_offsets = (struct attrcache_index *)(ahp + 1);
1446*5331Samw 		fgp->fg_alloclist = ((uchar_t *)fgp->fg_offsets) +
14470Sstevel@tonic-gate 			(fscp->fs_info.fi_fgsize *
14480Sstevel@tonic-gate 			sizeof (struct attrcache_index));
14490Sstevel@tonic-gate 		fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR;
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 		if ((cachep->c_flags & CACHE_CHECK_RLTYPE) &&
14520Sstevel@tonic-gate 		    (ahp->ach_rl_current == CACHEFS_RL_ATTRFILE)) {
14530Sstevel@tonic-gate 			rl_entry_t *rlp, rl;
14540Sstevel@tonic-gate 
14550Sstevel@tonic-gate 			mutex_enter(&cachep->c_contentslock);
14560Sstevel@tonic-gate 			error = cachefs_rl_entry_get(cachep, ahp->ach_rlno,
14570Sstevel@tonic-gate 									&rlp);
14580Sstevel@tonic-gate 			if (error) {
14590Sstevel@tonic-gate 				mutex_exit(&cachep->c_contentslock);
14600Sstevel@tonic-gate 				cachefs_kmem_free(ahp, fgp->fg_headersize);
14610Sstevel@tonic-gate 				fgp->fg_flags |= CFS_FG_NOCACHE;
14620Sstevel@tonic-gate 				VN_RELE(attrvp);
14630Sstevel@tonic-gate 				return (error);
14640Sstevel@tonic-gate 			}
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 			rl = *rlp;
14670Sstevel@tonic-gate 			mutex_exit(&cachep->c_contentslock);
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 			if (rl.rl_current != ahp->ach_rl_current) {
14700Sstevel@tonic-gate 				ahp->ach_rl_current = rl.rl_current;
14710Sstevel@tonic-gate 				fgp->fg_flags |= CFS_FG_UPDATED;
14720Sstevel@tonic-gate 			}
14730Sstevel@tonic-gate 		}
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 		/* if the attr file is on the rl */
14760Sstevel@tonic-gate 		if (fgp->fg_header->ach_rl_current == CACHEFS_RL_GC) {
14770Sstevel@tonic-gate #ifdef CFSDEBUG
14780Sstevel@tonic-gate 			if (fgp->fg_flags & CFS_FG_WRITE)
14790Sstevel@tonic-gate 				cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
14800Sstevel@tonic-gate 				    CACHEFS_RL_GC,
14810Sstevel@tonic-gate 				    fgp->fg_header->ach_rlno);
14820Sstevel@tonic-gate #endif /* CFSDEBUG */
14830Sstevel@tonic-gate 			if ((fgp->fg_count > 0) &&
14840Sstevel@tonic-gate 			    (fgp->fg_flags & CFS_FG_WRITE)) {
14850Sstevel@tonic-gate 				/* remove from rl, put on active */
14860Sstevel@tonic-gate 				cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
14870Sstevel@tonic-gate 				    CACHEFS_RL_ATTRFILE,
14880Sstevel@tonic-gate 				    fgp->fg_header->ach_rlno,
14890Sstevel@tonic-gate 				    fgp->fg_header->ach_nblks);
14900Sstevel@tonic-gate 				fgp->fg_header->ach_rl_current =
14910Sstevel@tonic-gate 				    CACHEFS_RL_ATTRFILE;
14920Sstevel@tonic-gate 				fgp->fg_flags |= CFS_FG_UPDATED;
14930Sstevel@tonic-gate 			}
14940Sstevel@tonic-gate 		} else {
14950Sstevel@tonic-gate 			ASSERT(fgp->fg_header->ach_rl_current ==
14960Sstevel@tonic-gate 			    CACHEFS_RL_ATTRFILE);
14970Sstevel@tonic-gate #ifdef CFSDEBUG
14980Sstevel@tonic-gate 			if (fgp->fg_flags & CFS_FG_WRITE)
14990Sstevel@tonic-gate 				cachefs_rlent_verify(fgp->fg_fscp->fs_cache,
15000Sstevel@tonic-gate 				    CACHEFS_RL_ATTRFILE,
15010Sstevel@tonic-gate 				    fgp->fg_header->ach_rlno);
15020Sstevel@tonic-gate #endif /* CFSDEBUG */
15030Sstevel@tonic-gate 		}
15040Sstevel@tonic-gate 	}
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate 	return (error);
15070Sstevel@tonic-gate }
15080Sstevel@tonic-gate 
15090Sstevel@tonic-gate /*
15100Sstevel@tonic-gate  * ------------------------------------------------------------------
15110Sstevel@tonic-gate  *
15120Sstevel@tonic-gate  *		filegrpdir_create
15130Sstevel@tonic-gate  *
15140Sstevel@tonic-gate  * Description:
15150Sstevel@tonic-gate  *	Creates the filegrp directory in the cache.
15160Sstevel@tonic-gate  *	If created CFS_FG_ALLOC_FILE is turned off.
15170Sstevel@tonic-gate  *	This routine should not be called if CFS_FG_ALLOC_FILE is
15180Sstevel@tonic-gate  *	already off.
15190Sstevel@tonic-gate  * Arguments:
15200Sstevel@tonic-gate  *	fgp	filegrp object
15210Sstevel@tonic-gate  * Returns:
15220Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
15230Sstevel@tonic-gate  * Preconditions:
15240Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
15250Sstevel@tonic-gate  *	precond(filegrp is writeable)
15260Sstevel@tonic-gate  */
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate int
filegrpdir_create(filegrp_t * fgp)15290Sstevel@tonic-gate filegrpdir_create(filegrp_t *fgp)
15300Sstevel@tonic-gate {
15310Sstevel@tonic-gate 	int error;
15320Sstevel@tonic-gate 	vnode_t *dirvp = NULL;
15330Sstevel@tonic-gate 	struct vattr *attrp = NULL;
15340Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
15350Sstevel@tonic-gate 	char *fname;
15360Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_WRITE);
15390Sstevel@tonic-gate 	ASSERT(CFS_ISFS_BACKFS_NFSV4(fscp) == 0);
15400Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&fgp->fg_mutex));
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	if (fgp->fg_flags & (CFS_FG_ALLOC_ATTR | CFS_FG_NOCACHE))
15430Sstevel@tonic-gate 		return (ENOENT);
15440Sstevel@tonic-gate 
15450Sstevel@tonic-gate 	/* allocate a 1 block file for the directory */
15460Sstevel@tonic-gate 	error = cachefs_allocfile(fscp->fs_cache);
15470Sstevel@tonic-gate 	if (error) {
15480Sstevel@tonic-gate 		return (error);
15490Sstevel@tonic-gate 	}
15500Sstevel@tonic-gate 	error = cachefs_allocblocks(fscp->fs_cache, 1,
15510Sstevel@tonic-gate 	    fgp->fg_header->ach_rl_current);
15520Sstevel@tonic-gate 	if (error) {
15530Sstevel@tonic-gate 		cachefs_freefile(fscp->fs_cache);
15540Sstevel@tonic-gate 		return (error);
15550Sstevel@tonic-gate 	}
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate 	/*
15580Sstevel@tonic-gate 	 * Construct a name for this file group directory and then do a mkdir
15590Sstevel@tonic-gate 	 */
15600Sstevel@tonic-gate 	make_ascii_name(&fgp->fg_id, name);
15610Sstevel@tonic-gate 	fname = name;
15620Sstevel@tonic-gate 	attrp = (struct vattr *)cachefs_kmem_alloc(sizeof (struct vattr),
15630Sstevel@tonic-gate 			KM_SLEEP);
15640Sstevel@tonic-gate 	attrp->va_mode = S_IFDIR | 0777;
15650Sstevel@tonic-gate 	attrp->va_uid = 0;
15660Sstevel@tonic-gate 	attrp->va_gid = 0;
15670Sstevel@tonic-gate 	attrp->va_type = VDIR;
15680Sstevel@tonic-gate 	attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
1569*5331Samw 	error = VOP_MKDIR(fscp->fs_fscdirvp, fname, attrp, &dirvp, kcred, NULL,
1570*5331Samw 	    0, NULL);
15710Sstevel@tonic-gate 	if (error) {
15720Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_NOCACHE;
15730Sstevel@tonic-gate 		cachefs_freefile(fscp->fs_cache);
15740Sstevel@tonic-gate 		cachefs_freeblocks(fscp->fs_cache, 1,
15750Sstevel@tonic-gate 		    fgp->fg_header->ach_rl_current);
15760Sstevel@tonic-gate 	} else {
15770Sstevel@tonic-gate 		fgp->fg_dirvp = dirvp;
15780Sstevel@tonic-gate 		fgp->fg_flags &= ~CFS_FG_ALLOC_FILE;
15790Sstevel@tonic-gate 	}
15800Sstevel@tonic-gate 
15810Sstevel@tonic-gate 	if (attrp)
15820Sstevel@tonic-gate 		cachefs_kmem_free(attrp, sizeof (*attrp));
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	return (error);
15850Sstevel@tonic-gate }
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate /*
15880Sstevel@tonic-gate  * ------------------------------------------------------------------
15890Sstevel@tonic-gate  *
15900Sstevel@tonic-gate  *		filegrpattr_create
15910Sstevel@tonic-gate  *
15920Sstevel@tonic-gate  * Description:
15930Sstevel@tonic-gate  *	Creates the attrcache file for the given filegrp.
15940Sstevel@tonic-gate  *	If created CFS_FG_ALLOC_ATTR is turned off.
15950Sstevel@tonic-gate  *	This routine should not be called if CFS_FG_ALLOC_ATTR is
15960Sstevel@tonic-gate  *	already off.
15970Sstevel@tonic-gate  * Arguments:
15980Sstevel@tonic-gate  *	fgp	filegrp object
15990Sstevel@tonic-gate  * Returns:
16000Sstevel@tonic-gate  *	Returns 0 on success, an errno value on failure.
16010Sstevel@tonic-gate  * Preconditions:
16020Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
16030Sstevel@tonic-gate  *	precond(filegrp is writable)
16040Sstevel@tonic-gate  */
16050Sstevel@tonic-gate 
16060Sstevel@tonic-gate int
filegrpattr_create(struct filegrp * fgp)16070Sstevel@tonic-gate filegrpattr_create(struct filegrp *fgp)
16080Sstevel@tonic-gate {
16090Sstevel@tonic-gate 	int error;
16100Sstevel@tonic-gate 	vnode_t *attrvp = NULL;
16110Sstevel@tonic-gate 	struct attrcache_header *ahp = NULL;
16120Sstevel@tonic-gate 	int nblks = 0;
16130Sstevel@tonic-gate 	int gotrlent = 0;
16140Sstevel@tonic-gate 	struct vattr *attrp = NULL;
16150Sstevel@tonic-gate 	char name[CFS_FRONTFILE_NAME_SIZE];
16160Sstevel@tonic-gate 	char *fname;
16170Sstevel@tonic-gate 	struct fscache *fscp = fgp->fg_fscp;
16180Sstevel@tonic-gate 	rl_entry_t rl_ent;
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 	ASSERT(fgp->fg_flags & CFS_FG_WRITE);
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 	if (fgp->fg_flags & CFS_FG_NOCACHE)
16230Sstevel@tonic-gate 		return (ENOENT);
16240Sstevel@tonic-gate 
16250Sstevel@tonic-gate 	cachefs_cache_dirty(fscp->fs_cache, 1);
16260Sstevel@tonic-gate 
16270Sstevel@tonic-gate 	/* allocate a file for the attrcache */
16280Sstevel@tonic-gate 	error = cachefs_allocfile(fscp->fs_cache);
16290Sstevel@tonic-gate 	if (error) {
16300Sstevel@tonic-gate 		goto out;
16310Sstevel@tonic-gate 	}
16320Sstevel@tonic-gate 
16330Sstevel@tonic-gate 	make_ascii_name(&fgp->fg_id, name);
16340Sstevel@tonic-gate 	fname = name;
16350Sstevel@tonic-gate 	attrp = cachefs_kmem_alloc(sizeof (struct vattr), KM_SLEEP);
16360Sstevel@tonic-gate 	attrp->va_mode = S_IFREG | 0666;
16370Sstevel@tonic-gate 	attrp->va_uid = 0;
16380Sstevel@tonic-gate 	attrp->va_gid = 0;
16390Sstevel@tonic-gate 	attrp->va_type = VREG;
16400Sstevel@tonic-gate 	attrp->va_mask = AT_TYPE | AT_MODE | AT_UID | AT_GID;
16410Sstevel@tonic-gate 	error = VOP_CREATE(fscp->fs_fsattrdir, fname, attrp, EXCL, 0666,
1642*5331Samw 			&attrvp, kcred, 0, NULL, NULL);
16430Sstevel@tonic-gate 	if (error) {
16440Sstevel@tonic-gate 		cachefs_freefile(fscp->fs_cache);
16450Sstevel@tonic-gate 		goto out;
16460Sstevel@tonic-gate 	}
16470Sstevel@tonic-gate 
16480Sstevel@tonic-gate 	/* alloc blocks for the attrcache header */
16490Sstevel@tonic-gate 	nblks = (fgp->fg_headersize + MAXBSIZE - 1) / MAXBSIZE;
16500Sstevel@tonic-gate 	error = cachefs_allocblocks(fscp->fs_cache, nblks, CACHEFS_RL_NONE);
16510Sstevel@tonic-gate 	if (error) {
16520Sstevel@tonic-gate 		nblks = 0;
16530Sstevel@tonic-gate 		goto out;
16540Sstevel@tonic-gate 	}
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	/* Construct an attrcache header */
16570Sstevel@tonic-gate 	ahp = cachefs_kmem_zalloc(fgp->fg_headersize, KM_SLEEP);
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 	/* write out the header to allocate space on ufs */
16600Sstevel@tonic-gate 	error = vn_rdwr(UIO_WRITE, attrvp, (caddr_t)ahp,
16610Sstevel@tonic-gate 	fgp->fg_headersize, 0LL, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
16620Sstevel@tonic-gate 		kcred, NULL);
16630Sstevel@tonic-gate 	if (error)
16640Sstevel@tonic-gate 		goto out;
16650Sstevel@tonic-gate 	error = filegrp_write_space(attrvp, (offset_t)fgp->fg_headersize,
16660Sstevel@tonic-gate 		(nblks * MAXBSIZE) - fgp->fg_headersize);
16670Sstevel@tonic-gate 	if (error)
16680Sstevel@tonic-gate 		goto out;
1669*5331Samw 	error = VOP_FSYNC(attrvp, FSYNC, kcred, NULL);
16700Sstevel@tonic-gate 	if (error)
16710Sstevel@tonic-gate 		goto out;
16720Sstevel@tonic-gate 
16730Sstevel@tonic-gate 	/* allocate an rl entry and mark it as an attrcache entry */
16740Sstevel@tonic-gate 	rl_ent.rl_fileno = fgp->fg_id.cid_fileno;
16750Sstevel@tonic-gate 	rl_ent.rl_local = (fgp->fg_id.cid_flags & CFS_CID_LOCAL) ? 1 : 0;
16760Sstevel@tonic-gate 	rl_ent.rl_fsid = fscp->fs_cfsid;
16770Sstevel@tonic-gate 	rl_ent.rl_attrc = 1;
16780Sstevel@tonic-gate 	error = cachefs_rl_alloc(fscp->fs_cache, &rl_ent, &ahp->ach_rlno);
16790Sstevel@tonic-gate 	if (error)
16800Sstevel@tonic-gate 		goto out;
16810Sstevel@tonic-gate 	gotrlent = 1;
16820Sstevel@tonic-gate 	if (fgp->fg_count == 0) {
16830Sstevel@tonic-gate 		/* put on the gc */
16840Sstevel@tonic-gate 		cachefs_rlent_moveto(fgp->fg_fscp->fs_cache, CACHEFS_RL_GC,
16850Sstevel@tonic-gate 		    ahp->ach_rlno, nblks);
16860Sstevel@tonic-gate 		ahp->ach_rl_current = CACHEFS_RL_GC;
16870Sstevel@tonic-gate 	} else {
16880Sstevel@tonic-gate 		/* put on attrfile list */
16890Sstevel@tonic-gate 		cachefs_rlent_moveto(fgp->fg_fscp->fs_cache,
16900Sstevel@tonic-gate 		    CACHEFS_RL_ATTRFILE, ahp->ach_rlno, nblks);
16910Sstevel@tonic-gate 		ahp->ach_rl_current = CACHEFS_RL_ATTRFILE;
16920Sstevel@tonic-gate 	}
16930Sstevel@tonic-gate 
16940Sstevel@tonic-gate out:
16950Sstevel@tonic-gate 	if (error) {
16960Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_NOCACHE;
16970Sstevel@tonic-gate 		if (attrvp) {
16980Sstevel@tonic-gate 			VN_RELE(attrvp);
1699*5331Samw 			(void) VOP_REMOVE(fscp->fs_fsattrdir, fname, kcred,
1700*5331Samw 			    NULL, 0);
17010Sstevel@tonic-gate 			cachefs_freefile(fscp->fs_cache);
17020Sstevel@tonic-gate 		}
17030Sstevel@tonic-gate 		if (nblks)
17040Sstevel@tonic-gate 			cachefs_freeblocks(fscp->fs_cache, nblks,
17050Sstevel@tonic-gate 			    CACHEFS_RL_NONE);
17060Sstevel@tonic-gate 		if (gotrlent)
17070Sstevel@tonic-gate 			cachefs_rlent_moveto(fscp->fs_cache,
17080Sstevel@tonic-gate 			    CACHEFS_RL_FREE, ahp->ach_rlno, 0);
17090Sstevel@tonic-gate 		if (ahp)
17100Sstevel@tonic-gate 			cachefs_kmem_free(ahp, fgp->fg_headersize);
17110Sstevel@tonic-gate 	} else {
17120Sstevel@tonic-gate 		fgp->fg_attrvp = attrvp;
17130Sstevel@tonic-gate 		fgp->fg_header = ahp;
17140Sstevel@tonic-gate 		fgp->fg_offsets = (struct attrcache_index *)(ahp + 1);
1715*5331Samw 		fgp->fg_alloclist = ((uchar_t *)fgp->fg_offsets) +
17160Sstevel@tonic-gate 			(fscp->fs_info.fi_fgsize *
17170Sstevel@tonic-gate 			sizeof (struct attrcache_index));
17180Sstevel@tonic-gate 		ahp->ach_count = 0;
17190Sstevel@tonic-gate 		ahp->ach_nffs = 0;
17200Sstevel@tonic-gate 		ahp->ach_nblks = nblks;
17210Sstevel@tonic-gate 		fgp->fg_flags &= ~CFS_FG_ALLOC_ATTR;
17220Sstevel@tonic-gate 		fgp->fg_flags |= CFS_FG_UPDATED;
17230Sstevel@tonic-gate 	}
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 	if (attrp)
17260Sstevel@tonic-gate 		cachefs_kmem_free(attrp, sizeof (*attrp));
17270Sstevel@tonic-gate 
17280Sstevel@tonic-gate 	return (error);
17290Sstevel@tonic-gate }
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate /*
17320Sstevel@tonic-gate  * ------------------------------------------------------------------
17330Sstevel@tonic-gate  *
17340Sstevel@tonic-gate  *		filegrp_cid_to_slot
17350Sstevel@tonic-gate  *
17360Sstevel@tonic-gate  * Description:
17370Sstevel@tonic-gate  *	Takes a file and returns the offset to the metadata
17380Sstevel@tonic-gate  *	slot for the specified filegrp.
17390Sstevel@tonic-gate  * Arguments:
17400Sstevel@tonic-gate  *	fgp	filegrp object
17410Sstevel@tonic-gate  *	cidp	file to map to an offset
17420Sstevel@tonic-gate  * Returns:
17430Sstevel@tonic-gate  *	Returns the offset or 0 if the slot is not allocated yet
17440Sstevel@tonic-gate  *	or it is invalid.
17450Sstevel@tonic-gate  * Preconditions:
17460Sstevel@tonic-gate  *	precond(fgp is a valid filegrp object)
17470Sstevel@tonic-gate  *	precond(fgp is not ALLOC_PENDING or NOCACHE)
17480Sstevel@tonic-gate  */
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate int
filegrp_cid_to_slot(filegrp_t * fgp,cfs_cid_t * cidp)17510Sstevel@tonic-gate filegrp_cid_to_slot(filegrp_t *fgp, cfs_cid_t *cidp)
17520Sstevel@tonic-gate {
17530Sstevel@tonic-gate 	int xx;
17540Sstevel@tonic-gate 	int slot;
17550Sstevel@tonic-gate 	int index;
17560Sstevel@tonic-gate 
1757*5331Samw 	index = (int)(cidp->cid_fileno - fgp->fg_id.cid_fileno);
17580Sstevel@tonic-gate 
17590Sstevel@tonic-gate 	if (index > fgp->fg_fscp->fs_info.fi_fgsize) {
17600Sstevel@tonic-gate 		cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
17610Sstevel@tonic-gate 		return (0);
17620Sstevel@tonic-gate 	}
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate 	slot = fgp->fg_offsets[index].ach_offset;
17650Sstevel@tonic-gate 	if (slot == 0)
17660Sstevel@tonic-gate 		return (0);
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate 	xx = fgp->fg_filesize - (int)sizeof (struct cfs_cachefs_metadata);
17690Sstevel@tonic-gate 	if ((slot < fgp->fg_headersize) || (xx < slot)) {
17700Sstevel@tonic-gate 		cmn_err(CE_WARN, "cachefs: attrcache error, run fsck");
17710Sstevel@tonic-gate 		return (0);
17720Sstevel@tonic-gate 	}
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate 	return (slot);
17750Sstevel@tonic-gate }
17760Sstevel@tonic-gate 
17770Sstevel@tonic-gate /*
17780Sstevel@tonic-gate  *
17790Sstevel@tonic-gate  *		filegrp_write_space
17800Sstevel@tonic-gate  *
17810Sstevel@tonic-gate  * Description:
17820Sstevel@tonic-gate  *	Writes garbage data to the specified file starting
17830Sstevel@tonic-gate  *	at the specified location for the specified number of bytes.
17840Sstevel@tonic-gate  *	slot for the specified filegrp.
17850Sstevel@tonic-gate  * Arguments:
17860Sstevel@tonic-gate  *	vp	vnode to write to
17870Sstevel@tonic-gate  *	offset	offset to write at
17880Sstevel@tonic-gate  *	cnt	number of bytes to write
17890Sstevel@tonic-gate  * Returns:
17900Sstevel@tonic-gate  *	Returns 0 for success or on error the result of the
17910Sstevel@tonic-gate  *	last vn_rdwr call.
17920Sstevel@tonic-gate  * Preconditions:
17930Sstevel@tonic-gate  *	precond(vp)
17940Sstevel@tonic-gate  */
17950Sstevel@tonic-gate 
17960Sstevel@tonic-gate int
filegrp_write_space(vnode_t * vp,offset_t offset,ssize_t cnt)17970Sstevel@tonic-gate filegrp_write_space(vnode_t *vp, offset_t offset, ssize_t cnt)
17980Sstevel@tonic-gate {
17990Sstevel@tonic-gate 	char *bufp;
18000Sstevel@tonic-gate 	int xx;
18010Sstevel@tonic-gate 	int error = 0;
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	bufp = (char *)cachefs_kmem_zalloc(MAXBSIZE, KM_SLEEP);
18040Sstevel@tonic-gate 	while (cnt > 0) {
18050Sstevel@tonic-gate 		if (cnt > MAXBSIZE)
18060Sstevel@tonic-gate 			xx = MAXBSIZE;
18070Sstevel@tonic-gate 		else
18080Sstevel@tonic-gate 			xx = (int)cnt;
18090Sstevel@tonic-gate 		error = vn_rdwr(UIO_WRITE, vp, (caddr_t)bufp,
18100Sstevel@tonic-gate 		xx, offset, UIO_SYSSPACE, 0, (rlim64_t)RLIM_INFINITY,
18110Sstevel@tonic-gate 			kcred, NULL);
18120Sstevel@tonic-gate 		if (error)
18130Sstevel@tonic-gate 			break;
18140Sstevel@tonic-gate 		offset += xx;
18150Sstevel@tonic-gate 		cnt -= xx;
18160Sstevel@tonic-gate 	}
18170Sstevel@tonic-gate 	cachefs_kmem_free(bufp, MAXBSIZE);
18180Sstevel@tonic-gate 	return (error);
18190Sstevel@tonic-gate }
1820