xref: /onnv-gate/usr/src/uts/common/fs/ufs/lufs_debug.c (revision 4662:9c48274ded8b)
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
5*4662Sfrankho  * Common Development and Distribution License (the "License").
6*4662Sfrankho  * 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
220Sstevel@tonic-gate 
230Sstevel@tonic-gate /*
24*4662Sfrankho  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
250Sstevel@tonic-gate  * Use is subject to license terms.
260Sstevel@tonic-gate  */
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #include <sys/systm.h>
290Sstevel@tonic-gate #include <sys/types.h>
300Sstevel@tonic-gate #include <sys/vnode.h>
310Sstevel@tonic-gate #include <sys/buf.h>
320Sstevel@tonic-gate #include <sys/ddi.h>
330Sstevel@tonic-gate #include <sys/errno.h>
340Sstevel@tonic-gate #include <sys/sysmacros.h>
350Sstevel@tonic-gate #include <sys/debug.h>
360Sstevel@tonic-gate #include <sys/kmem.h>
370Sstevel@tonic-gate #include <sys/conf.h>
380Sstevel@tonic-gate #include <sys/proc.h>
390Sstevel@tonic-gate #include <sys/cmn_err.h>
400Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
410Sstevel@tonic-gate #include <sys/fs/ufs_filio.h>
420Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
430Sstevel@tonic-gate 
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #ifdef	DEBUG
460Sstevel@tonic-gate 
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate  * DEBUG ROUTINES
490Sstevel@tonic-gate  *	THESE ROUTINES ARE ONLY USED WHEN ASSERTS ARE ENABLED
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static	kmutex_t	toptracelock;
530Sstevel@tonic-gate static	int		toptraceindex;
540Sstevel@tonic-gate int			toptracemax	= 1024;	/* global so it can be set */
550Sstevel@tonic-gate struct toptrace {
560Sstevel@tonic-gate 	enum delta_type	dtyp;
570Sstevel@tonic-gate 	kthread_t	*thread;
580Sstevel@tonic-gate 	dev_t		dev;
590Sstevel@tonic-gate 	long		arg2;
600Sstevel@tonic-gate 	long		arg3;
610Sstevel@tonic-gate 	long long	arg1;
620Sstevel@tonic-gate } *toptrace;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static void
top_trace(enum delta_type dtyp,dev_t dev,long long arg1,long arg2,long arg3)650Sstevel@tonic-gate top_trace(enum delta_type dtyp, dev_t dev, long long arg1, long arg2, long arg3)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate 	if (toptrace == NULL) {
680Sstevel@tonic-gate 		toptraceindex = 0;
690Sstevel@tonic-gate 		toptrace = kmem_zalloc((size_t)
700Sstevel@tonic-gate 		    (sizeof (struct toptrace) * toptracemax), KM_SLEEP);
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate 	mutex_enter(&toptracelock);
730Sstevel@tonic-gate 	toptrace[toptraceindex].dtyp = dtyp;
740Sstevel@tonic-gate 	toptrace[toptraceindex].thread = curthread;
750Sstevel@tonic-gate 	toptrace[toptraceindex].dev = dev;
760Sstevel@tonic-gate 	toptrace[toptraceindex].arg1 = arg1;
770Sstevel@tonic-gate 	toptrace[toptraceindex].arg2 = arg2;
780Sstevel@tonic-gate 	toptrace[toptraceindex].arg3 = arg3;
790Sstevel@tonic-gate 	if (++toptraceindex == toptracemax)
800Sstevel@tonic-gate 		toptraceindex = 0;
810Sstevel@tonic-gate 	else {
820Sstevel@tonic-gate 		toptrace[toptraceindex].dtyp = (enum delta_type)-1;
830Sstevel@tonic-gate 		toptrace[toptraceindex].thread = (kthread_t *)-1;
840Sstevel@tonic-gate 		toptrace[toptraceindex].dev = (dev_t)-1;
850Sstevel@tonic-gate 		toptrace[toptraceindex].arg1 = -1;
860Sstevel@tonic-gate 		toptrace[toptraceindex].arg2 = -1;
870Sstevel@tonic-gate 	}
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	mutex_exit(&toptracelock);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate  * add a range into the metadata map
940Sstevel@tonic-gate  */
950Sstevel@tonic-gate void
top_mataadd(ufsvfs_t * ufsvfsp,offset_t mof,off_t nb)960Sstevel@tonic-gate top_mataadd(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
970Sstevel@tonic-gate {
980Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1010Sstevel@tonic-gate 	deltamap_add(ul->un_matamap, mof, nb, 0, 0, 0, NULL);
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate  * delete a range from the metadata map
1060Sstevel@tonic-gate  */
1070Sstevel@tonic-gate void
top_matadel(ufsvfs_t * ufsvfsp,offset_t mof,off_t nb)1080Sstevel@tonic-gate top_matadel(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1130Sstevel@tonic-gate 	ASSERT(!matamap_overlap(ul->un_deltamap, mof, nb));
1140Sstevel@tonic-gate 	deltamap_del(ul->un_matamap, mof, nb);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate /*
1180Sstevel@tonic-gate  * clear the entries from the metadata map
1190Sstevel@tonic-gate  */
1200Sstevel@tonic-gate void
top_mataclr(ufsvfs_t * ufsvfsp)1210Sstevel@tonic-gate top_mataclr(ufsvfs_t *ufsvfsp)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1260Sstevel@tonic-gate 	map_free_entries(ul->un_matamap);
1270Sstevel@tonic-gate 	map_free_entries(ul->un_deltamap);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate int
top_begin_debug(ml_unit_t * ul,top_t topid,ulong_t size)1310Sstevel@tonic-gate top_begin_debug(ml_unit_t *ul, top_t topid, ulong_t size)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	threadtrans_t *tp;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
1360Sstevel@tonic-gate 		top_trace(DT_BOT, ul->un_dev,
137*4662Sfrankho 		    (long long)topid, (long)size, (long)0);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	tp = tsd_get(topkey);
1420Sstevel@tonic-gate 	if (tp == NULL) {
1430Sstevel@tonic-gate 		tp = kmem_zalloc(sizeof (threadtrans_t), KM_SLEEP);
1440Sstevel@tonic-gate 		(void) tsd_set(topkey, tp);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 	tp->topid  = topid;
1470Sstevel@tonic-gate 	tp->esize  = size;
1480Sstevel@tonic-gate 	tp->rsize  = 0;
1490Sstevel@tonic-gate 	tp->dev    = ul->un_dev;
1500Sstevel@tonic-gate 	return (1);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate int
top_end_debug(ml_unit_t * ul,mt_map_t * mtm,top_t topid,ulong_t size)1540Sstevel@tonic-gate top_end_debug(ml_unit_t *ul, mt_map_t *mtm, top_t topid, ulong_t size)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	threadtrans_t *tp;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	ASSERT((tp = (threadtrans_t *)tsd_get(topkey)) != NULL);
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	ASSERT((tp->dev == ul->un_dev) && (tp->topid == topid) &&
1630Sstevel@tonic-gate 	    (tp->esize == size));
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	ASSERT(((ul->un_debug & MT_SIZE) == 0) || (tp->rsize <= tp->esize));
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_num[topid]++;
1680Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_etot[topid] += tp->esize;
1690Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_rtot[topid] += tp->rsize;
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	if (tp->rsize > mtm->mtm_tops->mtm_top_size_max[topid])
1720Sstevel@tonic-gate 		mtm->mtm_tops->mtm_top_size_max[topid] = tp->rsize;
1730Sstevel@tonic-gate 	if (mtm->mtm_tops->mtm_top_size_min[topid] == 0)
1740Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
1750Sstevel@tonic-gate 			    tp->rsize;
1760Sstevel@tonic-gate 	else
1770Sstevel@tonic-gate 		if (tp->rsize < mtm->mtm_tops->mtm_top_size_min[topid])
1780Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
1790Sstevel@tonic-gate 			    tp->rsize;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
1820Sstevel@tonic-gate 		top_trace(DT_EOT, ul->un_dev, (long long)topid,
1830Sstevel@tonic-gate 		    (long)tp->rsize, (long)0);
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	return (1);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate int
top_delta_debug(ml_unit_t * ul,offset_t mof,off_t nb,delta_t dtyp)1890Sstevel@tonic-gate top_delta_debug(
1900Sstevel@tonic-gate 	ml_unit_t *ul,
1910Sstevel@tonic-gate 	offset_t mof,
1920Sstevel@tonic-gate 	off_t nb,
1930Sstevel@tonic-gate 	delta_t dtyp)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 	struct threadtrans	*tp;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	/*
2000Sstevel@tonic-gate 	 * check for delta contained fully within matamap
2010Sstevel@tonic-gate 	 */
2020Sstevel@tonic-gate 	ASSERT((ul->un_matamap == NULL) ||
203*4662Sfrankho 	    matamap_within(ul->un_matamap, mof, nb));
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	/*
2060Sstevel@tonic-gate 	 * maintain transaction info
2070Sstevel@tonic-gate 	 */
2080Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT)
2090Sstevel@tonic-gate 		ul->un_logmap->mtm_tops->mtm_delta_num[dtyp]++;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	/*
2120Sstevel@tonic-gate 	 * check transaction stuff
2130Sstevel@tonic-gate 	 */
2140Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT) {
2150Sstevel@tonic-gate 		tp = (struct threadtrans *)tsd_get(topkey);
2160Sstevel@tonic-gate 		ASSERT(tp);
2170Sstevel@tonic-gate 		switch (dtyp) {
2180Sstevel@tonic-gate 		case DT_CANCEL:
2190Sstevel@tonic-gate 		case DT_ABZERO:
2200Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
2210Sstevel@tonic-gate 				tp->rsize += sizeof (struct delta);
2220Sstevel@tonic-gate 			break;
2230Sstevel@tonic-gate 		default:
2240Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
2250Sstevel@tonic-gate 				tp->rsize += nb + sizeof (struct delta);
2260Sstevel@tonic-gate 			break;
2270Sstevel@tonic-gate 		}
2280Sstevel@tonic-gate 	} else
2290Sstevel@tonic-gate 		return (1);
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
2320Sstevel@tonic-gate 		top_trace(dtyp, ul->un_dev, mof, (long)nb, (long)0);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	return (1);
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate int
top_roll_debug(ml_unit_t * ul)2380Sstevel@tonic-gate top_roll_debug(ml_unit_t *ul)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	logmap_roll_dev(ul);
2410Sstevel@tonic-gate 	return (1);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate int
top_init_debug(void)2450Sstevel@tonic-gate top_init_debug(void)
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate 	mutex_init(&toptracelock, NULL, MUTEX_DEFAULT, NULL);
2480Sstevel@tonic-gate 	return (1);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate struct topstats_link {
2520Sstevel@tonic-gate 	struct topstats_link	*ts_next;
2530Sstevel@tonic-gate 	dev_t			ts_dev;
2540Sstevel@tonic-gate 	struct topstats		ts_stats;
2550Sstevel@tonic-gate };
2560Sstevel@tonic-gate struct topstats_link *topstats_anchor = NULL;
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate  * DEBUG ROUTINES
2600Sstevel@tonic-gate  *	from debug portion of *_map.c
2610Sstevel@tonic-gate  */
2620Sstevel@tonic-gate /*
2630Sstevel@tonic-gate  * scan test support
2640Sstevel@tonic-gate  */
2650Sstevel@tonic-gate int
logmap_logscan_debug(mt_map_t * mtm,mapentry_t * age)2660Sstevel@tonic-gate logmap_logscan_debug(mt_map_t *mtm, mapentry_t *age)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate 	mapentry_t	*me;
2690Sstevel@tonic-gate 	ml_unit_t	*ul;
2700Sstevel@tonic-gate 	off_t		head, trimroll, lof;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	/*
2730Sstevel@tonic-gate 	 * remember location of youngest rolled delta
2740Sstevel@tonic-gate 	 */
2750Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
2760Sstevel@tonic-gate 	ul = mtm->mtm_ul;
2770Sstevel@tonic-gate 	head = ul->un_head_lof;
2780Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
2790Sstevel@tonic-gate 	for (me = age; me; me = me->me_agenext) {
2800Sstevel@tonic-gate 		lof = me->me_lof;
2810Sstevel@tonic-gate 		if (trimroll == 0)
2820Sstevel@tonic-gate 			trimroll = lof;
2830Sstevel@tonic-gate 		if (lof >= head) {
2840Sstevel@tonic-gate 			if (trimroll >= head && trimroll <= lof)
2850Sstevel@tonic-gate 				trimroll = lof;
2860Sstevel@tonic-gate 		} else {
2870Sstevel@tonic-gate 			if (trimroll <= lof || trimroll >= head)
2880Sstevel@tonic-gate 				trimroll = lof;
2890Sstevel@tonic-gate 		}
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 	mtm->mtm_trimrlof = trimroll;
2920Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
2930Sstevel@tonic-gate 	return (1);
2940Sstevel@tonic-gate }
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate  * scan test support
2980Sstevel@tonic-gate  */
2990Sstevel@tonic-gate int
logmap_logscan_commit_debug(off_t lof,mt_map_t * mtm)3000Sstevel@tonic-gate logmap_logscan_commit_debug(off_t lof, mt_map_t *mtm)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate 	off_t	oldtrimc, newtrimc, trimroll;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
3050Sstevel@tonic-gate 	oldtrimc = mtm->mtm_trimclof;
3060Sstevel@tonic-gate 	newtrimc = mtm->mtm_trimclof = dbtob(btod(lof));
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	/*
3090Sstevel@tonic-gate 	 * can't trim prior to transaction w/rolled delta
3100Sstevel@tonic-gate 	 */
3110Sstevel@tonic-gate 	if (trimroll)
3120Sstevel@tonic-gate 		if (newtrimc >= oldtrimc) {
3130Sstevel@tonic-gate 			if (trimroll <= newtrimc && trimroll >= oldtrimc)
3140Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
3150Sstevel@tonic-gate 		} else {
3160Sstevel@tonic-gate 			if (trimroll >= oldtrimc || trimroll <= newtrimc)
3170Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
3180Sstevel@tonic-gate 		}
3190Sstevel@tonic-gate 	return (1);
3200Sstevel@tonic-gate }
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate int
logmap_logscan_add_debug(struct delta * dp,mt_map_t * mtm)3230Sstevel@tonic-gate logmap_logscan_add_debug(struct delta *dp, mt_map_t *mtm)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	if ((dp->d_typ == DT_AB) || (dp->d_typ == DT_INODE))
3260Sstevel@tonic-gate 		mtm->mtm_trimalof = mtm->mtm_trimclof;
3270Sstevel@tonic-gate 	return (1);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate  * log-read after log-write
3320Sstevel@tonic-gate  */
3330Sstevel@tonic-gate int
map_check_ldl_write(ml_unit_t * ul,caddr_t va,offset_t vamof,mapentry_t * me)3340Sstevel@tonic-gate map_check_ldl_write(ml_unit_t *ul, caddr_t va, offset_t vamof, mapentry_t *me)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate 	caddr_t		bufp;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	ASSERT(me->me_nb);
3390Sstevel@tonic-gate 	ASSERT((me->me_flags & ME_AGE) == 0);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	/* Alloc a buf */
3420Sstevel@tonic-gate 	bufp = kmem_alloc(me->me_nb, KM_SLEEP);
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	/* Do the read */
3450Sstevel@tonic-gate 	me->me_agenext = NULL;
3460Sstevel@tonic-gate 	if (ldl_read(ul, bufp, me->me_mof, me->me_nb, me) == 0) {
3470Sstevel@tonic-gate 		ASSERT(bcmp(bufp, va + (me->me_mof - vamof), me->me_nb) == 0);
3480Sstevel@tonic-gate 	}
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 	kmem_free(bufp, me->me_nb);
3510Sstevel@tonic-gate 	return (1);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate  * Cleanup a map struct
3560Sstevel@tonic-gate  */
3570Sstevel@tonic-gate int
map_put_debug(mt_map_t * mtm)3580Sstevel@tonic-gate map_put_debug(mt_map_t *mtm)
3590Sstevel@tonic-gate {
3600Sstevel@tonic-gate 	struct topstats_link	*tsl, **ptsl;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	if (mtm->mtm_tops == NULL)
3630Sstevel@tonic-gate 		return (1);
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	/* Don't free this, cause the next snarf will want it */
3660Sstevel@tonic-gate 	if ((lufs_debug & MT_TRANSACT) != 0)
3670Sstevel@tonic-gate 		return (1);
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	ptsl = &topstats_anchor;
3700Sstevel@tonic-gate 	tsl = topstats_anchor;
3710Sstevel@tonic-gate 	while (tsl) {
3720Sstevel@tonic-gate 		if (mtm->mtm_tops == &tsl->ts_stats) {
3730Sstevel@tonic-gate 			mtm->mtm_tops = NULL;
3740Sstevel@tonic-gate 			*ptsl = tsl->ts_next;
3750Sstevel@tonic-gate 			kmem_free(tsl, sizeof (*tsl));
3760Sstevel@tonic-gate 			return (1);
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		ptsl = &tsl->ts_next;
3790Sstevel@tonic-gate 		tsl = tsl->ts_next;
3800Sstevel@tonic-gate 	}
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	return (1);
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate int
map_get_debug(ml_unit_t * ul,mt_map_t * mtm)3860Sstevel@tonic-gate map_get_debug(ml_unit_t *ul, mt_map_t *mtm)
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate 	struct topstats_link	*tsl;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	if ((ul->un_debug & MT_TRANSACT) == 0)
3910Sstevel@tonic-gate 		return (1);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	if (mtm->mtm_type != logmaptype)
3940Sstevel@tonic-gate 		return (1);
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	tsl = topstats_anchor;
3970Sstevel@tonic-gate 	while (tsl) {
3980Sstevel@tonic-gate 		if (tsl->ts_dev == ul->un_dev) {
3990Sstevel@tonic-gate 			mtm->mtm_tops = &(tsl->ts_stats);
4000Sstevel@tonic-gate 			return (1);
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 		tsl = tsl->ts_next;
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	tsl = kmem_zalloc(sizeof (*tsl), KM_SLEEP);
4060Sstevel@tonic-gate 	tsl->ts_dev = ul->un_dev;
4070Sstevel@tonic-gate 	tsl->ts_next = topstats_anchor;
4080Sstevel@tonic-gate 	topstats_anchor = tsl;
4090Sstevel@tonic-gate 	mtm->mtm_tops = &tsl->ts_stats;
4100Sstevel@tonic-gate 	return (1);
4110Sstevel@tonic-gate }
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate  * check a map's list
4150Sstevel@tonic-gate  */
4160Sstevel@tonic-gate int
map_check_linkage(mt_map_t * mtm)4170Sstevel@tonic-gate map_check_linkage(mt_map_t *mtm)
4180Sstevel@tonic-gate {
4190Sstevel@tonic-gate 	int		i;
4200Sstevel@tonic-gate 	int		hashed;
4210Sstevel@tonic-gate 	int		nexted;
4220Sstevel@tonic-gate 	int		preved;
4230Sstevel@tonic-gate 	int		ncancel;
4240Sstevel@tonic-gate 	mapentry_t	*me;
4250Sstevel@tonic-gate 	off_t		olof;
4260Sstevel@tonic-gate 	off_t		firstlof;
4270Sstevel@tonic-gate 	int		wrapped;
4280Sstevel@tonic-gate 
4290Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	ASSERT(mtm->mtm_nme >= 0);
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	/*
4340Sstevel@tonic-gate 	 * verify the entries on the hash
4350Sstevel@tonic-gate 	 */
4360Sstevel@tonic-gate 	hashed = 0;
4370Sstevel@tonic-gate 	for (i = 0; i < mtm->mtm_nhash; ++i) {
4380Sstevel@tonic-gate 		for (me = *(mtm->mtm_hash+i); me; me = me->me_hash) {
4390Sstevel@tonic-gate 			++hashed;
4400Sstevel@tonic-gate 			ASSERT(me->me_flags & ME_HASH);
4410Sstevel@tonic-gate 			ASSERT((me->me_flags & ME_LIST) == 0);
4420Sstevel@tonic-gate 		}
4430Sstevel@tonic-gate 	}
4440Sstevel@tonic-gate 	ASSERT(hashed >= mtm->mtm_nme);
4450Sstevel@tonic-gate 	/*
4460Sstevel@tonic-gate 	 * verify the doubly linked list of all entries
4470Sstevel@tonic-gate 	 */
4480Sstevel@tonic-gate 	nexted = 0;
4490Sstevel@tonic-gate 	for (me = mtm->mtm_next; me != (mapentry_t *)mtm; me = me->me_next)
4500Sstevel@tonic-gate 		nexted++;
4510Sstevel@tonic-gate 	preved = 0;
4520Sstevel@tonic-gate 	for (me = mtm->mtm_prev; me != (mapentry_t *)mtm; me = me->me_prev)
4530Sstevel@tonic-gate 		preved++;
4540Sstevel@tonic-gate 	ASSERT(nexted == preved);
4550Sstevel@tonic-gate 	ASSERT(nexted == hashed);
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	/*
4580Sstevel@tonic-gate 	 * verify the cancel list
4590Sstevel@tonic-gate 	 */
4600Sstevel@tonic-gate 	ncancel = 0;
4610Sstevel@tonic-gate 	for (me = mtm->mtm_cancel; me; me = me->me_cancel) {
4620Sstevel@tonic-gate 		++ncancel;
4630Sstevel@tonic-gate 		ASSERT(me->me_flags & ME_CANCEL);
4640Sstevel@tonic-gate 	}
4650Sstevel@tonic-gate 	/*
4660Sstevel@tonic-gate 	 * verify the logmap's log offsets
4670Sstevel@tonic-gate 	 */
4680Sstevel@tonic-gate 	if (mtm->mtm_type == logmaptype) {
4690Sstevel@tonic-gate 		olof = mtm->mtm_next->me_lof;
4700Sstevel@tonic-gate 		firstlof = olof;
4710Sstevel@tonic-gate 		wrapped = 0;
4720Sstevel@tonic-gate 		/*
4730Sstevel@tonic-gate 		 * Make sure to skip any mapentries whose me_lof = 0
4740Sstevel@tonic-gate 		 * and me_type == DT_CANCEL, these are mapentries
4750Sstevel@tonic-gate 		 * in place just to mark user block deletions as not
4760Sstevel@tonic-gate 		 * available for allocate within the same moby transaction
4770Sstevel@tonic-gate 		 * in case we crash before it is comitted.  Skip these
4780Sstevel@tonic-gate 		 * entries in the checks below as they are not applicable.
4790Sstevel@tonic-gate 		 */
4800Sstevel@tonic-gate 		for (me = mtm->mtm_next->me_next;
4810Sstevel@tonic-gate 		    me != (mapentry_t *)mtm;
4820Sstevel@tonic-gate 		    me = me->me_next) {
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 			if (me->me_lof == 0 && me->me_dt == DT_CANCEL)
4850Sstevel@tonic-gate 				continue;
4860Sstevel@tonic-gate 			if (firstlof == 0) {
4870Sstevel@tonic-gate 				olof = me->me_lof;
4880Sstevel@tonic-gate 				firstlof = olof;
4890Sstevel@tonic-gate 				if (me->me_next != (mapentry_t *)mtm)
4900Sstevel@tonic-gate 					me = me->me_next;
4910Sstevel@tonic-gate 				continue;
4920Sstevel@tonic-gate 			}
4930Sstevel@tonic-gate 			ASSERT(me->me_lof != olof);
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 			if (wrapped) {
4960Sstevel@tonic-gate 				ASSERT(me->me_lof > olof);
4970Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
4980Sstevel@tonic-gate 				olof = me->me_lof;
4990Sstevel@tonic-gate 				continue;
5000Sstevel@tonic-gate 			}
5010Sstevel@tonic-gate 			if (me->me_lof < olof) {
5020Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
5030Sstevel@tonic-gate 				wrapped = 1;
5040Sstevel@tonic-gate 				olof = me->me_lof;
5050Sstevel@tonic-gate 				continue;
5060Sstevel@tonic-gate 			}
5070Sstevel@tonic-gate 			ASSERT(me->me_lof > firstlof);
5080Sstevel@tonic-gate 			ASSERT(me->me_lof < mtm->mtm_ul->un_eol_lof);
5090Sstevel@tonic-gate 			olof = me->me_lof;
5100Sstevel@tonic-gate 		}
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
5140Sstevel@tonic-gate 	return (1);
5150Sstevel@tonic-gate }
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate /*
5180Sstevel@tonic-gate  * check for overlap
5190Sstevel@tonic-gate  */
5200Sstevel@tonic-gate int
matamap_overlap(mt_map_t * mtm,offset_t mof,off_t nb)5210Sstevel@tonic-gate matamap_overlap(mt_map_t *mtm, offset_t mof, off_t nb)
5220Sstevel@tonic-gate {
5230Sstevel@tonic-gate 	off_t		hnb;
5240Sstevel@tonic-gate 	mapentry_t	*me;
5250Sstevel@tonic-gate 	mapentry_t	**mep;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	for (hnb = 0; nb; nb -= hnb, mof += hnb) {
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
5300Sstevel@tonic-gate 		if (hnb > nb)
5310Sstevel@tonic-gate 			hnb = nb;
5320Sstevel@tonic-gate 		/*
5330Sstevel@tonic-gate 		 * search for dup entry
5340Sstevel@tonic-gate 		 */
5350Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
5360Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
5370Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
5380Sstevel@tonic-gate 			if (DATAoverlapME(mof, hnb, me))
5390Sstevel@tonic-gate 				break;
5400Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 		/*
5430Sstevel@tonic-gate 		 * overlap detected
5440Sstevel@tonic-gate 		 */
5450Sstevel@tonic-gate 		if (me)
5460Sstevel@tonic-gate 			return (1);
5470Sstevel@tonic-gate 	}
5480Sstevel@tonic-gate 	return (0);
5490Sstevel@tonic-gate }
5500Sstevel@tonic-gate /*
5510Sstevel@tonic-gate  * check for within
5520Sstevel@tonic-gate  */
5530Sstevel@tonic-gate int
matamap_within(mt_map_t * mtm,offset_t mof,off_t nb)5540Sstevel@tonic-gate matamap_within(mt_map_t *mtm, offset_t mof, off_t nb)
5550Sstevel@tonic-gate {
5560Sstevel@tonic-gate 	off_t		hnb;
5570Sstevel@tonic-gate 	mapentry_t	*me;
5580Sstevel@tonic-gate 	mapentry_t	**mep;
5590Sstevel@tonic-gate 	int		scans	= 0;
5600Sstevel@tonic-gate 	int		withins	= 0;
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	for (hnb = 0; nb && scans == withins; nb -= hnb, mof += hnb) {
5630Sstevel@tonic-gate 		scans++;
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
5660Sstevel@tonic-gate 		if (hnb > nb)
5670Sstevel@tonic-gate 			hnb = nb;
5680Sstevel@tonic-gate 		/*
5690Sstevel@tonic-gate 		 * search for within entry
5700Sstevel@tonic-gate 		 */
5710Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
5720Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
5730Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
5740Sstevel@tonic-gate 			if (DATAwithinME(mof, hnb, me)) {
5750Sstevel@tonic-gate 				withins++;
5760Sstevel@tonic-gate 				break;
5770Sstevel@tonic-gate 			}
5780Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 	return (scans == withins);
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate int
ldl_sethead_debug(ml_unit_t * ul)5840Sstevel@tonic-gate ldl_sethead_debug(ml_unit_t *ul)
5850Sstevel@tonic-gate {
5860Sstevel@tonic-gate 	mt_map_t	*mtm	= ul->un_logmap;
5870Sstevel@tonic-gate 	off_t		trimr	= mtm->mtm_trimrlof;
5880Sstevel@tonic-gate 	off_t		head	= ul->un_head_lof;
5890Sstevel@tonic-gate 	off_t		tail	= ul->un_tail_lof;
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	if (head <= tail) {
5920Sstevel@tonic-gate 		if (trimr < head || trimr >= tail)
5930Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
5940Sstevel@tonic-gate 	} else {
5950Sstevel@tonic-gate 		if (trimr >= tail && trimr < head)
5960Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 	return (1);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate 
6010Sstevel@tonic-gate int
lufs_initialize_debug(ml_odunit_t * ud)6020Sstevel@tonic-gate lufs_initialize_debug(ml_odunit_t *ud)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	ud->od_debug = lufs_debug;
6050Sstevel@tonic-gate 	return (1);
6060Sstevel@tonic-gate }
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate #endif	/* DEBUG */
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate /*
6110Sstevel@tonic-gate  * lufs_debug controls the debug level for TSufs, and is only used
6120Sstevel@tonic-gate  * for a debug kernel. It's referenced by ufs_ioctl() and so is
6130Sstevel@tonic-gate  * not under #ifdef DEBUG compilation.
6140Sstevel@tonic-gate  */
6150Sstevel@tonic-gate uint_t lufs_debug;
616