xref: /illumos-gate/usr/src/uts/common/fs/ufs/lufs_debug.c (revision 2d6eb4a5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*80d34432Sfrankho  * Common Development and Distribution License (the "License").
6*80d34432Sfrankho  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate /*
23*80d34432Sfrankho  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/systm.h>
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
307c478bd9Sstevel@tonic-gate #include <sys/buf.h>
317c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/errno.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/debug.h>
357c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
367c478bd9Sstevel@tonic-gate #include <sys/conf.h>
377c478bd9Sstevel@tonic-gate #include <sys/proc.h>
387c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
397c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
407c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_filio.h>
417c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifdef	DEBUG
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * DEBUG ROUTINES
487c478bd9Sstevel@tonic-gate  *	THESE ROUTINES ARE ONLY USED WHEN ASSERTS ARE ENABLED
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate static	kmutex_t	toptracelock;
527c478bd9Sstevel@tonic-gate static	int		toptraceindex;
537c478bd9Sstevel@tonic-gate int			toptracemax	= 1024;	/* global so it can be set */
547c478bd9Sstevel@tonic-gate struct toptrace {
557c478bd9Sstevel@tonic-gate 	enum delta_type	dtyp;
567c478bd9Sstevel@tonic-gate 	kthread_t	*thread;
577c478bd9Sstevel@tonic-gate 	dev_t		dev;
587c478bd9Sstevel@tonic-gate 	long		arg2;
597c478bd9Sstevel@tonic-gate 	long		arg3;
607c478bd9Sstevel@tonic-gate 	long long	arg1;
617c478bd9Sstevel@tonic-gate } *toptrace;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate static void
top_trace(enum delta_type dtyp,dev_t dev,long long arg1,long arg2,long arg3)647c478bd9Sstevel@tonic-gate top_trace(enum delta_type dtyp, dev_t dev, long long arg1, long arg2, long arg3)
657c478bd9Sstevel@tonic-gate {
667c478bd9Sstevel@tonic-gate 	if (toptrace == NULL) {
677c478bd9Sstevel@tonic-gate 		toptraceindex = 0;
687c478bd9Sstevel@tonic-gate 		toptrace = kmem_zalloc((size_t)
697c478bd9Sstevel@tonic-gate 		    (sizeof (struct toptrace) * toptracemax), KM_SLEEP);
707c478bd9Sstevel@tonic-gate 	}
717c478bd9Sstevel@tonic-gate 	mutex_enter(&toptracelock);
727c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].dtyp = dtyp;
737c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].thread = curthread;
747c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].dev = dev;
757c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg1 = arg1;
767c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg2 = arg2;
777c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg3 = arg3;
787c478bd9Sstevel@tonic-gate 	if (++toptraceindex == toptracemax)
797c478bd9Sstevel@tonic-gate 		toptraceindex = 0;
807c478bd9Sstevel@tonic-gate 	else {
817c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].dtyp = (enum delta_type)-1;
827c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].thread = (kthread_t *)-1;
837c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].dev = (dev_t)-1;
847c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].arg1 = -1;
857c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].arg2 = -1;
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	mutex_exit(&toptracelock);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate  * add a range into the metadata map
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate void
top_mataadd(ufsvfs_t * ufsvfsp,offset_t mof,off_t nb)957c478bd9Sstevel@tonic-gate top_mataadd(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1007c478bd9Sstevel@tonic-gate 	deltamap_add(ul->un_matamap, mof, nb, 0, 0, 0, NULL);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * delete a range from the metadata map
1057c478bd9Sstevel@tonic-gate  */
1067c478bd9Sstevel@tonic-gate void
top_matadel(ufsvfs_t * ufsvfsp,offset_t mof,off_t nb)1077c478bd9Sstevel@tonic-gate top_matadel(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1127c478bd9Sstevel@tonic-gate 	ASSERT(!matamap_overlap(ul->un_deltamap, mof, nb));
1137c478bd9Sstevel@tonic-gate 	deltamap_del(ul->un_matamap, mof, nb);
1147c478bd9Sstevel@tonic-gate }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * clear the entries from the metadata map
1187c478bd9Sstevel@tonic-gate  */
1197c478bd9Sstevel@tonic-gate void
top_mataclr(ufsvfs_t * ufsvfsp)1207c478bd9Sstevel@tonic-gate top_mataclr(ufsvfs_t *ufsvfsp)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
1257c478bd9Sstevel@tonic-gate 	map_free_entries(ul->un_matamap);
1267c478bd9Sstevel@tonic-gate 	map_free_entries(ul->un_deltamap);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate int
top_begin_debug(ml_unit_t * ul,top_t topid,ulong_t size)1307c478bd9Sstevel@tonic-gate top_begin_debug(ml_unit_t *ul, top_t topid, ulong_t size)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	threadtrans_t *tp;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
1357c478bd9Sstevel@tonic-gate 		top_trace(DT_BOT, ul->un_dev,
136*80d34432Sfrankho 		    (long long)topid, (long)size, (long)0);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	tp = tsd_get(topkey);
1417c478bd9Sstevel@tonic-gate 	if (tp == NULL) {
1427c478bd9Sstevel@tonic-gate 		tp = kmem_zalloc(sizeof (threadtrans_t), KM_SLEEP);
1437c478bd9Sstevel@tonic-gate 		(void) tsd_set(topkey, tp);
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	tp->topid  = topid;
1467c478bd9Sstevel@tonic-gate 	tp->esize  = size;
1477c478bd9Sstevel@tonic-gate 	tp->rsize  = 0;
1487c478bd9Sstevel@tonic-gate 	tp->dev    = ul->un_dev;
1497c478bd9Sstevel@tonic-gate 	return (1);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate int
top_end_debug(ml_unit_t * ul,mt_map_t * mtm,top_t topid,ulong_t size)1537c478bd9Sstevel@tonic-gate top_end_debug(ml_unit_t *ul, mt_map_t *mtm, top_t topid, ulong_t size)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	threadtrans_t *tp;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	ASSERT((tp = (threadtrans_t *)tsd_get(topkey)) != NULL);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	ASSERT((tp->dev == ul->un_dev) && (tp->topid == topid) &&
1627c478bd9Sstevel@tonic-gate 	    (tp->esize == size));
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	ASSERT(((ul->un_debug & MT_SIZE) == 0) || (tp->rsize <= tp->esize));
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_num[topid]++;
1677c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_etot[topid] += tp->esize;
1687c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_rtot[topid] += tp->rsize;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	if (tp->rsize > mtm->mtm_tops->mtm_top_size_max[topid])
1717c478bd9Sstevel@tonic-gate 		mtm->mtm_tops->mtm_top_size_max[topid] = tp->rsize;
1727c478bd9Sstevel@tonic-gate 	if (mtm->mtm_tops->mtm_top_size_min[topid] == 0)
1737c478bd9Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
1747c478bd9Sstevel@tonic-gate 			    tp->rsize;
1757c478bd9Sstevel@tonic-gate 	else
1767c478bd9Sstevel@tonic-gate 		if (tp->rsize < mtm->mtm_tops->mtm_top_size_min[topid])
1777c478bd9Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
1787c478bd9Sstevel@tonic-gate 			    tp->rsize;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
1817c478bd9Sstevel@tonic-gate 		top_trace(DT_EOT, ul->un_dev, (long long)topid,
1827c478bd9Sstevel@tonic-gate 		    (long)tp->rsize, (long)0);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	return (1);
1857c478bd9Sstevel@tonic-gate }
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate int
top_delta_debug(ml_unit_t * ul,offset_t mof,off_t nb,delta_t dtyp)1887c478bd9Sstevel@tonic-gate top_delta_debug(
1897c478bd9Sstevel@tonic-gate 	ml_unit_t *ul,
1907c478bd9Sstevel@tonic-gate 	offset_t mof,
1917c478bd9Sstevel@tonic-gate 	off_t nb,
1927c478bd9Sstevel@tonic-gate 	delta_t dtyp)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	struct threadtrans	*tp;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	/*
1997c478bd9Sstevel@tonic-gate 	 * check for delta contained fully within matamap
2007c478bd9Sstevel@tonic-gate 	 */
2017c478bd9Sstevel@tonic-gate 	ASSERT((ul->un_matamap == NULL) ||
202*80d34432Sfrankho 	    matamap_within(ul->un_matamap, mof, nb));
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	/*
2057c478bd9Sstevel@tonic-gate 	 * maintain transaction info
2067c478bd9Sstevel@tonic-gate 	 */
2077c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT)
2087c478bd9Sstevel@tonic-gate 		ul->un_logmap->mtm_tops->mtm_delta_num[dtyp]++;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	/*
2117c478bd9Sstevel@tonic-gate 	 * check transaction stuff
2127c478bd9Sstevel@tonic-gate 	 */
2137c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT) {
2147c478bd9Sstevel@tonic-gate 		tp = (struct threadtrans *)tsd_get(topkey);
2157c478bd9Sstevel@tonic-gate 		ASSERT(tp);
2167c478bd9Sstevel@tonic-gate 		switch (dtyp) {
2177c478bd9Sstevel@tonic-gate 		case DT_CANCEL:
2187c478bd9Sstevel@tonic-gate 		case DT_ABZERO:
2197c478bd9Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
2207c478bd9Sstevel@tonic-gate 				tp->rsize += sizeof (struct delta);
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 		default:
2237c478bd9Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
2247c478bd9Sstevel@tonic-gate 				tp->rsize += nb + sizeof (struct delta);
2257c478bd9Sstevel@tonic-gate 			break;
2267c478bd9Sstevel@tonic-gate 		}
2277c478bd9Sstevel@tonic-gate 	} else
2287c478bd9Sstevel@tonic-gate 		return (1);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
2317c478bd9Sstevel@tonic-gate 		top_trace(dtyp, ul->un_dev, mof, (long)nb, (long)0);
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	return (1);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate int
top_roll_debug(ml_unit_t * ul)2377c478bd9Sstevel@tonic-gate top_roll_debug(ml_unit_t *ul)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	logmap_roll_dev(ul);
2407c478bd9Sstevel@tonic-gate 	return (1);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate int
top_init_debug(void)2447c478bd9Sstevel@tonic-gate top_init_debug(void)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	mutex_init(&toptracelock, NULL, MUTEX_DEFAULT, NULL);
2477c478bd9Sstevel@tonic-gate 	return (1);
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate struct topstats_link {
2517c478bd9Sstevel@tonic-gate 	struct topstats_link	*ts_next;
2527c478bd9Sstevel@tonic-gate 	dev_t			ts_dev;
2537c478bd9Sstevel@tonic-gate 	struct topstats		ts_stats;
2547c478bd9Sstevel@tonic-gate };
2557c478bd9Sstevel@tonic-gate struct topstats_link *topstats_anchor = NULL;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate  * DEBUG ROUTINES
2597c478bd9Sstevel@tonic-gate  *	from debug portion of *_map.c
2607c478bd9Sstevel@tonic-gate  */
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * scan test support
2637c478bd9Sstevel@tonic-gate  */
2647c478bd9Sstevel@tonic-gate int
logmap_logscan_debug(mt_map_t * mtm,mapentry_t * age)2657c478bd9Sstevel@tonic-gate logmap_logscan_debug(mt_map_t *mtm, mapentry_t *age)
2667c478bd9Sstevel@tonic-gate {
2677c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
2687c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul;
2697c478bd9Sstevel@tonic-gate 	off_t		head, trimroll, lof;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	/*
2727c478bd9Sstevel@tonic-gate 	 * remember location of youngest rolled delta
2737c478bd9Sstevel@tonic-gate 	 */
2747c478bd9Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
2757c478bd9Sstevel@tonic-gate 	ul = mtm->mtm_ul;
2767c478bd9Sstevel@tonic-gate 	head = ul->un_head_lof;
2777c478bd9Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
2787c478bd9Sstevel@tonic-gate 	for (me = age; me; me = me->me_agenext) {
2797c478bd9Sstevel@tonic-gate 		lof = me->me_lof;
2807c478bd9Sstevel@tonic-gate 		if (trimroll == 0)
2817c478bd9Sstevel@tonic-gate 			trimroll = lof;
2827c478bd9Sstevel@tonic-gate 		if (lof >= head) {
2837c478bd9Sstevel@tonic-gate 			if (trimroll >= head && trimroll <= lof)
2847c478bd9Sstevel@tonic-gate 				trimroll = lof;
2857c478bd9Sstevel@tonic-gate 		} else {
2867c478bd9Sstevel@tonic-gate 			if (trimroll <= lof || trimroll >= head)
2877c478bd9Sstevel@tonic-gate 				trimroll = lof;
2887c478bd9Sstevel@tonic-gate 		}
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 	mtm->mtm_trimrlof = trimroll;
2917c478bd9Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
2927c478bd9Sstevel@tonic-gate 	return (1);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate /*
2967c478bd9Sstevel@tonic-gate  * scan test support
2977c478bd9Sstevel@tonic-gate  */
2987c478bd9Sstevel@tonic-gate int
logmap_logscan_commit_debug(off_t lof,mt_map_t * mtm)2997c478bd9Sstevel@tonic-gate logmap_logscan_commit_debug(off_t lof, mt_map_t *mtm)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	off_t	oldtrimc, newtrimc, trimroll;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
3047c478bd9Sstevel@tonic-gate 	oldtrimc = mtm->mtm_trimclof;
3057c478bd9Sstevel@tonic-gate 	newtrimc = mtm->mtm_trimclof = dbtob(btod(lof));
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	/*
3087c478bd9Sstevel@tonic-gate 	 * can't trim prior to transaction w/rolled delta
3097c478bd9Sstevel@tonic-gate 	 */
3107c478bd9Sstevel@tonic-gate 	if (trimroll)
3117c478bd9Sstevel@tonic-gate 		if (newtrimc >= oldtrimc) {
3127c478bd9Sstevel@tonic-gate 			if (trimroll <= newtrimc && trimroll >= oldtrimc)
3137c478bd9Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
3147c478bd9Sstevel@tonic-gate 		} else {
3157c478bd9Sstevel@tonic-gate 			if (trimroll >= oldtrimc || trimroll <= newtrimc)
3167c478bd9Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
3177c478bd9Sstevel@tonic-gate 		}
3187c478bd9Sstevel@tonic-gate 	return (1);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate int
logmap_logscan_add_debug(struct delta * dp,mt_map_t * mtm)3227c478bd9Sstevel@tonic-gate logmap_logscan_add_debug(struct delta *dp, mt_map_t *mtm)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate 	if ((dp->d_typ == DT_AB) || (dp->d_typ == DT_INODE))
3257c478bd9Sstevel@tonic-gate 		mtm->mtm_trimalof = mtm->mtm_trimclof;
3267c478bd9Sstevel@tonic-gate 	return (1);
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate /*
3307c478bd9Sstevel@tonic-gate  * log-read after log-write
3317c478bd9Sstevel@tonic-gate  */
3327c478bd9Sstevel@tonic-gate int
map_check_ldl_write(ml_unit_t * ul,caddr_t va,offset_t vamof,mapentry_t * me)3337c478bd9Sstevel@tonic-gate map_check_ldl_write(ml_unit_t *ul, caddr_t va, offset_t vamof, mapentry_t *me)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate 	caddr_t		bufp;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	ASSERT(me->me_nb);
3387c478bd9Sstevel@tonic-gate 	ASSERT((me->me_flags & ME_AGE) == 0);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	/* Alloc a buf */
3417c478bd9Sstevel@tonic-gate 	bufp = kmem_alloc(me->me_nb, KM_SLEEP);
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	/* Do the read */
3447c478bd9Sstevel@tonic-gate 	me->me_agenext = NULL;
3457c478bd9Sstevel@tonic-gate 	if (ldl_read(ul, bufp, me->me_mof, me->me_nb, me) == 0) {
3467c478bd9Sstevel@tonic-gate 		ASSERT(bcmp(bufp, va + (me->me_mof - vamof), me->me_nb) == 0);
3477c478bd9Sstevel@tonic-gate 	}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	kmem_free(bufp, me->me_nb);
3507c478bd9Sstevel@tonic-gate 	return (1);
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate  * Cleanup a map struct
3557c478bd9Sstevel@tonic-gate  */
3567c478bd9Sstevel@tonic-gate int
map_put_debug(mt_map_t * mtm)3577c478bd9Sstevel@tonic-gate map_put_debug(mt_map_t *mtm)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate 	struct topstats_link	*tsl, **ptsl;
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	if (mtm->mtm_tops == NULL)
3627c478bd9Sstevel@tonic-gate 		return (1);
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/* Don't free this, cause the next snarf will want it */
3657c478bd9Sstevel@tonic-gate 	if ((lufs_debug & MT_TRANSACT) != 0)
3667c478bd9Sstevel@tonic-gate 		return (1);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate 	ptsl = &topstats_anchor;
3697c478bd9Sstevel@tonic-gate 	tsl = topstats_anchor;
3707c478bd9Sstevel@tonic-gate 	while (tsl) {
3717c478bd9Sstevel@tonic-gate 		if (mtm->mtm_tops == &tsl->ts_stats) {
3727c478bd9Sstevel@tonic-gate 			mtm->mtm_tops = NULL;
3737c478bd9Sstevel@tonic-gate 			*ptsl = tsl->ts_next;
3747c478bd9Sstevel@tonic-gate 			kmem_free(tsl, sizeof (*tsl));
3757c478bd9Sstevel@tonic-gate 			return (1);
3767c478bd9Sstevel@tonic-gate 		}
3777c478bd9Sstevel@tonic-gate 		ptsl = &tsl->ts_next;
3787c478bd9Sstevel@tonic-gate 		tsl = tsl->ts_next;
3797c478bd9Sstevel@tonic-gate 	}
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	return (1);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate int
map_get_debug(ml_unit_t * ul,mt_map_t * mtm)3857c478bd9Sstevel@tonic-gate map_get_debug(ml_unit_t *ul, mt_map_t *mtm)
3867c478bd9Sstevel@tonic-gate {
3877c478bd9Sstevel@tonic-gate 	struct topstats_link	*tsl;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	if ((ul->un_debug & MT_TRANSACT) == 0)
3907c478bd9Sstevel@tonic-gate 		return (1);
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (mtm->mtm_type != logmaptype)
3937c478bd9Sstevel@tonic-gate 		return (1);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	tsl = topstats_anchor;
3967c478bd9Sstevel@tonic-gate 	while (tsl) {
3977c478bd9Sstevel@tonic-gate 		if (tsl->ts_dev == ul->un_dev) {
3987c478bd9Sstevel@tonic-gate 			mtm->mtm_tops = &(tsl->ts_stats);
3997c478bd9Sstevel@tonic-gate 			return (1);
4007c478bd9Sstevel@tonic-gate 		}
4017c478bd9Sstevel@tonic-gate 		tsl = tsl->ts_next;
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	tsl = kmem_zalloc(sizeof (*tsl), KM_SLEEP);
4057c478bd9Sstevel@tonic-gate 	tsl->ts_dev = ul->un_dev;
4067c478bd9Sstevel@tonic-gate 	tsl->ts_next = topstats_anchor;
4077c478bd9Sstevel@tonic-gate 	topstats_anchor = tsl;
4087c478bd9Sstevel@tonic-gate 	mtm->mtm_tops = &tsl->ts_stats;
4097c478bd9Sstevel@tonic-gate 	return (1);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate  * check a map's list
4147c478bd9Sstevel@tonic-gate  */
4157c478bd9Sstevel@tonic-gate int
map_check_linkage(mt_map_t * mtm)4167c478bd9Sstevel@tonic-gate map_check_linkage(mt_map_t *mtm)
4177c478bd9Sstevel@tonic-gate {
4187c478bd9Sstevel@tonic-gate 	int		i;
4197c478bd9Sstevel@tonic-gate 	int		hashed;
4207c478bd9Sstevel@tonic-gate 	int		nexted;
4217c478bd9Sstevel@tonic-gate 	int		preved;
4227c478bd9Sstevel@tonic-gate 	int		ncancel;
4237c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
4247c478bd9Sstevel@tonic-gate 	off_t		olof;
4257c478bd9Sstevel@tonic-gate 	off_t		firstlof;
4267c478bd9Sstevel@tonic-gate 	int		wrapped;
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	ASSERT(mtm->mtm_nme >= 0);
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/*
4337c478bd9Sstevel@tonic-gate 	 * verify the entries on the hash
4347c478bd9Sstevel@tonic-gate 	 */
4357c478bd9Sstevel@tonic-gate 	hashed = 0;
4367c478bd9Sstevel@tonic-gate 	for (i = 0; i < mtm->mtm_nhash; ++i) {
4377c478bd9Sstevel@tonic-gate 		for (me = *(mtm->mtm_hash+i); me; me = me->me_hash) {
4387c478bd9Sstevel@tonic-gate 			++hashed;
4397c478bd9Sstevel@tonic-gate 			ASSERT(me->me_flags & ME_HASH);
4407c478bd9Sstevel@tonic-gate 			ASSERT((me->me_flags & ME_LIST) == 0);
4417c478bd9Sstevel@tonic-gate 		}
4427c478bd9Sstevel@tonic-gate 	}
4437c478bd9Sstevel@tonic-gate 	ASSERT(hashed >= mtm->mtm_nme);
4447c478bd9Sstevel@tonic-gate 	/*
4457c478bd9Sstevel@tonic-gate 	 * verify the doubly linked list of all entries
4467c478bd9Sstevel@tonic-gate 	 */
4477c478bd9Sstevel@tonic-gate 	nexted = 0;
4487c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_next; me != (mapentry_t *)mtm; me = me->me_next)
4497c478bd9Sstevel@tonic-gate 		nexted++;
4507c478bd9Sstevel@tonic-gate 	preved = 0;
4517c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_prev; me != (mapentry_t *)mtm; me = me->me_prev)
4527c478bd9Sstevel@tonic-gate 		preved++;
4537c478bd9Sstevel@tonic-gate 	ASSERT(nexted == preved);
4547c478bd9Sstevel@tonic-gate 	ASSERT(nexted == hashed);
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	/*
4577c478bd9Sstevel@tonic-gate 	 * verify the cancel list
4587c478bd9Sstevel@tonic-gate 	 */
4597c478bd9Sstevel@tonic-gate 	ncancel = 0;
4607c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_cancel; me; me = me->me_cancel) {
4617c478bd9Sstevel@tonic-gate 		++ncancel;
4627c478bd9Sstevel@tonic-gate 		ASSERT(me->me_flags & ME_CANCEL);
4637c478bd9Sstevel@tonic-gate 	}
4647c478bd9Sstevel@tonic-gate 	/*
4657c478bd9Sstevel@tonic-gate 	 * verify the logmap's log offsets
4667c478bd9Sstevel@tonic-gate 	 */
4677c478bd9Sstevel@tonic-gate 	if (mtm->mtm_type == logmaptype) {
4687c478bd9Sstevel@tonic-gate 		olof = mtm->mtm_next->me_lof;
4697c478bd9Sstevel@tonic-gate 		firstlof = olof;
4707c478bd9Sstevel@tonic-gate 		wrapped = 0;
4717c478bd9Sstevel@tonic-gate 		/*
4727c478bd9Sstevel@tonic-gate 		 * Make sure to skip any mapentries whose me_lof = 0
4737c478bd9Sstevel@tonic-gate 		 * and me_type == DT_CANCEL, these are mapentries
4747c478bd9Sstevel@tonic-gate 		 * in place just to mark user block deletions as not
4757c478bd9Sstevel@tonic-gate 		 * available for allocate within the same moby transaction
4767c478bd9Sstevel@tonic-gate 		 * in case we crash before it is comitted.  Skip these
4777c478bd9Sstevel@tonic-gate 		 * entries in the checks below as they are not applicable.
4787c478bd9Sstevel@tonic-gate 		 */
4797c478bd9Sstevel@tonic-gate 		for (me = mtm->mtm_next->me_next;
4807c478bd9Sstevel@tonic-gate 		    me != (mapentry_t *)mtm;
4817c478bd9Sstevel@tonic-gate 		    me = me->me_next) {
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 			if (me->me_lof == 0 && me->me_dt == DT_CANCEL)
4847c478bd9Sstevel@tonic-gate 				continue;
4857c478bd9Sstevel@tonic-gate 			if (firstlof == 0) {
4867c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
4877c478bd9Sstevel@tonic-gate 				firstlof = olof;
4887c478bd9Sstevel@tonic-gate 				if (me->me_next != (mapentry_t *)mtm)
4897c478bd9Sstevel@tonic-gate 					me = me->me_next;
4907c478bd9Sstevel@tonic-gate 				continue;
4917c478bd9Sstevel@tonic-gate 			}
4927c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof != olof);
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 			if (wrapped) {
4957c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof > olof);
4967c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
4977c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
4987c478bd9Sstevel@tonic-gate 				continue;
4997c478bd9Sstevel@tonic-gate 			}
5007c478bd9Sstevel@tonic-gate 			if (me->me_lof < olof) {
5017c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
5027c478bd9Sstevel@tonic-gate 				wrapped = 1;
5037c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
5047c478bd9Sstevel@tonic-gate 				continue;
5057c478bd9Sstevel@tonic-gate 			}
5067c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof > firstlof);
5077c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof < mtm->mtm_ul->un_eol_lof);
5087c478bd9Sstevel@tonic-gate 			olof = me->me_lof;
5097c478bd9Sstevel@tonic-gate 		}
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
5137c478bd9Sstevel@tonic-gate 	return (1);
5147c478bd9Sstevel@tonic-gate }
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate /*
5177c478bd9Sstevel@tonic-gate  * check for overlap
5187c478bd9Sstevel@tonic-gate  */
5197c478bd9Sstevel@tonic-gate int
matamap_overlap(mt_map_t * mtm,offset_t mof,off_t nb)5207c478bd9Sstevel@tonic-gate matamap_overlap(mt_map_t *mtm, offset_t mof, off_t nb)
5217c478bd9Sstevel@tonic-gate {
5227c478bd9Sstevel@tonic-gate 	off_t		hnb;
5237c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
5247c478bd9Sstevel@tonic-gate 	mapentry_t	**mep;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	for (hnb = 0; nb; nb -= hnb, mof += hnb) {
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
5297c478bd9Sstevel@tonic-gate 		if (hnb > nb)
5307c478bd9Sstevel@tonic-gate 			hnb = nb;
5317c478bd9Sstevel@tonic-gate 		/*
5327c478bd9Sstevel@tonic-gate 		 * search for dup entry
5337c478bd9Sstevel@tonic-gate 		 */
5347c478bd9Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
5357c478bd9Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
5367c478bd9Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
5377c478bd9Sstevel@tonic-gate 			if (DATAoverlapME(mof, hnb, me))
5387c478bd9Sstevel@tonic-gate 				break;
5397c478bd9Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 		/*
5427c478bd9Sstevel@tonic-gate 		 * overlap detected
5437c478bd9Sstevel@tonic-gate 		 */
5447c478bd9Sstevel@tonic-gate 		if (me)
5457c478bd9Sstevel@tonic-gate 			return (1);
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 	return (0);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate /*
5507c478bd9Sstevel@tonic-gate  * check for within
5517c478bd9Sstevel@tonic-gate  */
5527c478bd9Sstevel@tonic-gate int
matamap_within(mt_map_t * mtm,offset_t mof,off_t nb)5537c478bd9Sstevel@tonic-gate matamap_within(mt_map_t *mtm, offset_t mof, off_t nb)
5547c478bd9Sstevel@tonic-gate {
5557c478bd9Sstevel@tonic-gate 	off_t		hnb;
5567c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
5577c478bd9Sstevel@tonic-gate 	mapentry_t	**mep;
5587c478bd9Sstevel@tonic-gate 	int		scans	= 0;
5597c478bd9Sstevel@tonic-gate 	int		withins	= 0;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	for (hnb = 0; nb && scans == withins; nb -= hnb, mof += hnb) {
5627c478bd9Sstevel@tonic-gate 		scans++;
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
5657c478bd9Sstevel@tonic-gate 		if (hnb > nb)
5667c478bd9Sstevel@tonic-gate 			hnb = nb;
5677c478bd9Sstevel@tonic-gate 		/*
5687c478bd9Sstevel@tonic-gate 		 * search for within entry
5697c478bd9Sstevel@tonic-gate 		 */
5707c478bd9Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
5717c478bd9Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
5727c478bd9Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
5737c478bd9Sstevel@tonic-gate 			if (DATAwithinME(mof, hnb, me)) {
5747c478bd9Sstevel@tonic-gate 				withins++;
5757c478bd9Sstevel@tonic-gate 				break;
5767c478bd9Sstevel@tonic-gate 			}
5777c478bd9Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
5787c478bd9Sstevel@tonic-gate 	}
5797c478bd9Sstevel@tonic-gate 	return (scans == withins);
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate int
ldl_sethead_debug(ml_unit_t * ul)5837c478bd9Sstevel@tonic-gate ldl_sethead_debug(ml_unit_t *ul)
5847c478bd9Sstevel@tonic-gate {
5857c478bd9Sstevel@tonic-gate 	mt_map_t	*mtm	= ul->un_logmap;
5867c478bd9Sstevel@tonic-gate 	off_t		trimr	= mtm->mtm_trimrlof;
5877c478bd9Sstevel@tonic-gate 	off_t		head	= ul->un_head_lof;
5887c478bd9Sstevel@tonic-gate 	off_t		tail	= ul->un_tail_lof;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	if (head <= tail) {
5917c478bd9Sstevel@tonic-gate 		if (trimr < head || trimr >= tail)
5927c478bd9Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
5937c478bd9Sstevel@tonic-gate 	} else {
5947c478bd9Sstevel@tonic-gate 		if (trimr >= tail && trimr < head)
5957c478bd9Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
5967c478bd9Sstevel@tonic-gate 	}
5977c478bd9Sstevel@tonic-gate 	return (1);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate int
lufs_initialize_debug(ml_odunit_t * ud)6017c478bd9Sstevel@tonic-gate lufs_initialize_debug(ml_odunit_t *ud)
6027c478bd9Sstevel@tonic-gate {
6037c478bd9Sstevel@tonic-gate 	ud->od_debug = lufs_debug;
6047c478bd9Sstevel@tonic-gate 	return (1);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate  * lufs_debug controls the debug level for TSufs, and is only used
6117c478bd9Sstevel@tonic-gate  * for a debug kernel. It's referenced by ufs_ioctl() and so is
6127c478bd9Sstevel@tonic-gate  * not under #ifdef DEBUG compilation.
6137c478bd9Sstevel@tonic-gate  */
6147c478bd9Sstevel@tonic-gate uint_t lufs_debug;
615