xref: /illumos-gate/usr/src/uts/common/fs/ufs/lufs_debug.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate /*
25*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
27*7c478bd9Sstevel@tonic-gate  */
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_filio.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate /*
49*7c478bd9Sstevel@tonic-gate  * DEBUG ROUTINES
50*7c478bd9Sstevel@tonic-gate  *	THESE ROUTINES ARE ONLY USED WHEN ASSERTS ARE ENABLED
51*7c478bd9Sstevel@tonic-gate  */
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate static	kmutex_t	toptracelock;
54*7c478bd9Sstevel@tonic-gate static	int		toptraceindex;
55*7c478bd9Sstevel@tonic-gate int			toptracemax	= 1024;	/* global so it can be set */
56*7c478bd9Sstevel@tonic-gate struct toptrace {
57*7c478bd9Sstevel@tonic-gate 	enum delta_type	dtyp;
58*7c478bd9Sstevel@tonic-gate 	kthread_t	*thread;
59*7c478bd9Sstevel@tonic-gate 	dev_t		dev;
60*7c478bd9Sstevel@tonic-gate 	long		arg2;
61*7c478bd9Sstevel@tonic-gate 	long		arg3;
62*7c478bd9Sstevel@tonic-gate 	long long	arg1;
63*7c478bd9Sstevel@tonic-gate } *toptrace;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static void
66*7c478bd9Sstevel@tonic-gate top_trace(enum delta_type dtyp, dev_t dev, long long arg1, long arg2, long arg3)
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	if (toptrace == NULL) {
69*7c478bd9Sstevel@tonic-gate 		toptraceindex = 0;
70*7c478bd9Sstevel@tonic-gate 		toptrace = kmem_zalloc((size_t)
71*7c478bd9Sstevel@tonic-gate 		    (sizeof (struct toptrace) * toptracemax), KM_SLEEP);
72*7c478bd9Sstevel@tonic-gate 	}
73*7c478bd9Sstevel@tonic-gate 	mutex_enter(&toptracelock);
74*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].dtyp = dtyp;
75*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].thread = curthread;
76*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].dev = dev;
77*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg1 = arg1;
78*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg2 = arg2;
79*7c478bd9Sstevel@tonic-gate 	toptrace[toptraceindex].arg3 = arg3;
80*7c478bd9Sstevel@tonic-gate 	if (++toptraceindex == toptracemax)
81*7c478bd9Sstevel@tonic-gate 		toptraceindex = 0;
82*7c478bd9Sstevel@tonic-gate 	else {
83*7c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].dtyp = (enum delta_type)-1;
84*7c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].thread = (kthread_t *)-1;
85*7c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].dev = (dev_t)-1;
86*7c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].arg1 = -1;
87*7c478bd9Sstevel@tonic-gate 		toptrace[toptraceindex].arg2 = -1;
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	mutex_exit(&toptracelock);
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate /*
94*7c478bd9Sstevel@tonic-gate  * add a range into the metadata map
95*7c478bd9Sstevel@tonic-gate  */
96*7c478bd9Sstevel@tonic-gate void
97*7c478bd9Sstevel@tonic-gate top_mataadd(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
98*7c478bd9Sstevel@tonic-gate {
99*7c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
102*7c478bd9Sstevel@tonic-gate 	deltamap_add(ul->un_matamap, mof, nb, 0, 0, 0, NULL);
103*7c478bd9Sstevel@tonic-gate }
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate /*
106*7c478bd9Sstevel@tonic-gate  * delete a range from the metadata map
107*7c478bd9Sstevel@tonic-gate  */
108*7c478bd9Sstevel@tonic-gate void
109*7c478bd9Sstevel@tonic-gate top_matadel(ufsvfs_t *ufsvfsp, offset_t mof, off_t nb)
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
114*7c478bd9Sstevel@tonic-gate 	ASSERT(!matamap_overlap(ul->un_deltamap, mof, nb));
115*7c478bd9Sstevel@tonic-gate 	deltamap_del(ul->un_matamap, mof, nb);
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate /*
119*7c478bd9Sstevel@tonic-gate  * clear the entries from the metadata map
120*7c478bd9Sstevel@tonic-gate  */
121*7c478bd9Sstevel@tonic-gate void
122*7c478bd9Sstevel@tonic-gate top_mataclr(ufsvfs_t *ufsvfsp)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul	= ufsvfsp->vfs_log;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	ASSERT(ufsvfsp->vfs_dev == ul->un_dev);
127*7c478bd9Sstevel@tonic-gate 	map_free_entries(ul->un_matamap);
128*7c478bd9Sstevel@tonic-gate 	map_free_entries(ul->un_deltamap);
129*7c478bd9Sstevel@tonic-gate }
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate int
132*7c478bd9Sstevel@tonic-gate top_begin_debug(ml_unit_t *ul, top_t topid, ulong_t size)
133*7c478bd9Sstevel@tonic-gate {
134*7c478bd9Sstevel@tonic-gate 	threadtrans_t *tp;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
137*7c478bd9Sstevel@tonic-gate 		top_trace(DT_BOT, ul->un_dev,
138*7c478bd9Sstevel@tonic-gate 				(long long)topid, (long)size, (long)0);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	tp = tsd_get(topkey);
143*7c478bd9Sstevel@tonic-gate 	if (tp == NULL) {
144*7c478bd9Sstevel@tonic-gate 		tp = kmem_zalloc(sizeof (threadtrans_t), KM_SLEEP);
145*7c478bd9Sstevel@tonic-gate 		(void) tsd_set(topkey, tp);
146*7c478bd9Sstevel@tonic-gate 	}
147*7c478bd9Sstevel@tonic-gate 	tp->topid  = topid;
148*7c478bd9Sstevel@tonic-gate 	tp->esize  = size;
149*7c478bd9Sstevel@tonic-gate 	tp->rsize  = 0;
150*7c478bd9Sstevel@tonic-gate 	tp->dev    = ul->un_dev;
151*7c478bd9Sstevel@tonic-gate 	return (1);
152*7c478bd9Sstevel@tonic-gate }
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate int
155*7c478bd9Sstevel@tonic-gate top_end_debug(ml_unit_t *ul, mt_map_t *mtm, top_t topid, ulong_t size)
156*7c478bd9Sstevel@tonic-gate {
157*7c478bd9Sstevel@tonic-gate 	threadtrans_t *tp;
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	ASSERT((tp = (threadtrans_t *)tsd_get(topkey)) != NULL);
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	ASSERT((tp->dev == ul->un_dev) && (tp->topid == topid) &&
164*7c478bd9Sstevel@tonic-gate 	    (tp->esize == size));
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	ASSERT(((ul->un_debug & MT_SIZE) == 0) || (tp->rsize <= tp->esize));
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_num[topid]++;
169*7c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_etot[topid] += tp->esize;
170*7c478bd9Sstevel@tonic-gate 	mtm->mtm_tops->mtm_top_size_rtot[topid] += tp->rsize;
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (tp->rsize > mtm->mtm_tops->mtm_top_size_max[topid])
173*7c478bd9Sstevel@tonic-gate 		mtm->mtm_tops->mtm_top_size_max[topid] = tp->rsize;
174*7c478bd9Sstevel@tonic-gate 	if (mtm->mtm_tops->mtm_top_size_min[topid] == 0)
175*7c478bd9Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
176*7c478bd9Sstevel@tonic-gate 			    tp->rsize;
177*7c478bd9Sstevel@tonic-gate 	else
178*7c478bd9Sstevel@tonic-gate 		if (tp->rsize < mtm->mtm_tops->mtm_top_size_min[topid])
179*7c478bd9Sstevel@tonic-gate 			mtm->mtm_tops->mtm_top_size_min[topid] =
180*7c478bd9Sstevel@tonic-gate 			    tp->rsize;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
183*7c478bd9Sstevel@tonic-gate 		top_trace(DT_EOT, ul->un_dev, (long long)topid,
184*7c478bd9Sstevel@tonic-gate 		    (long)tp->rsize, (long)0);
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	return (1);
187*7c478bd9Sstevel@tonic-gate }
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate int
190*7c478bd9Sstevel@tonic-gate top_delta_debug(
191*7c478bd9Sstevel@tonic-gate 	ml_unit_t *ul,
192*7c478bd9Sstevel@tonic-gate 	offset_t mof,
193*7c478bd9Sstevel@tonic-gate 	off_t nb,
194*7c478bd9Sstevel@tonic-gate 	delta_t dtyp)
195*7c478bd9Sstevel@tonic-gate {
196*7c478bd9Sstevel@tonic-gate 	struct threadtrans	*tp;
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	ASSERT(curthread->t_flag & T_DONTBLOCK);
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 	/*
201*7c478bd9Sstevel@tonic-gate 	 * check for delta contained fully within matamap
202*7c478bd9Sstevel@tonic-gate 	 */
203*7c478bd9Sstevel@tonic-gate 	ASSERT((ul->un_matamap == NULL) ||
204*7c478bd9Sstevel@tonic-gate 		matamap_within(ul->un_matamap, mof, nb));
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	/*
207*7c478bd9Sstevel@tonic-gate 	 * maintain transaction info
208*7c478bd9Sstevel@tonic-gate 	 */
209*7c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT)
210*7c478bd9Sstevel@tonic-gate 		ul->un_logmap->mtm_tops->mtm_delta_num[dtyp]++;
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	/*
213*7c478bd9Sstevel@tonic-gate 	 * check transaction stuff
214*7c478bd9Sstevel@tonic-gate 	 */
215*7c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRANSACT) {
216*7c478bd9Sstevel@tonic-gate 		tp = (struct threadtrans *)tsd_get(topkey);
217*7c478bd9Sstevel@tonic-gate 		ASSERT(tp);
218*7c478bd9Sstevel@tonic-gate 		switch (dtyp) {
219*7c478bd9Sstevel@tonic-gate 		case DT_CANCEL:
220*7c478bd9Sstevel@tonic-gate 		case DT_ABZERO:
221*7c478bd9Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
222*7c478bd9Sstevel@tonic-gate 				tp->rsize += sizeof (struct delta);
223*7c478bd9Sstevel@tonic-gate 			break;
224*7c478bd9Sstevel@tonic-gate 		default:
225*7c478bd9Sstevel@tonic-gate 			if (!matamap_within(ul->un_deltamap, mof, nb))
226*7c478bd9Sstevel@tonic-gate 				tp->rsize += nb + sizeof (struct delta);
227*7c478bd9Sstevel@tonic-gate 			break;
228*7c478bd9Sstevel@tonic-gate 		}
229*7c478bd9Sstevel@tonic-gate 	} else
230*7c478bd9Sstevel@tonic-gate 		return (1);
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate 	if (ul->un_debug & MT_TRACE)
233*7c478bd9Sstevel@tonic-gate 		top_trace(dtyp, ul->un_dev, mof, (long)nb, (long)0);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	return (1);
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate int
239*7c478bd9Sstevel@tonic-gate top_roll_debug(ml_unit_t *ul)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	logmap_roll_dev(ul);
242*7c478bd9Sstevel@tonic-gate 	return (1);
243*7c478bd9Sstevel@tonic-gate }
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate int
246*7c478bd9Sstevel@tonic-gate top_init_debug(void)
247*7c478bd9Sstevel@tonic-gate {
248*7c478bd9Sstevel@tonic-gate 	mutex_init(&toptracelock, NULL, MUTEX_DEFAULT, NULL);
249*7c478bd9Sstevel@tonic-gate 	return (1);
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate struct topstats_link {
253*7c478bd9Sstevel@tonic-gate 	struct topstats_link	*ts_next;
254*7c478bd9Sstevel@tonic-gate 	dev_t			ts_dev;
255*7c478bd9Sstevel@tonic-gate 	struct topstats		ts_stats;
256*7c478bd9Sstevel@tonic-gate };
257*7c478bd9Sstevel@tonic-gate struct topstats_link *topstats_anchor = NULL;
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate  * DEBUG ROUTINES
261*7c478bd9Sstevel@tonic-gate  *	from debug portion of *_map.c
262*7c478bd9Sstevel@tonic-gate  */
263*7c478bd9Sstevel@tonic-gate /*
264*7c478bd9Sstevel@tonic-gate  * scan test support
265*7c478bd9Sstevel@tonic-gate  */
266*7c478bd9Sstevel@tonic-gate int
267*7c478bd9Sstevel@tonic-gate logmap_logscan_debug(mt_map_t *mtm, mapentry_t *age)
268*7c478bd9Sstevel@tonic-gate {
269*7c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
270*7c478bd9Sstevel@tonic-gate 	ml_unit_t	*ul;
271*7c478bd9Sstevel@tonic-gate 	off_t		head, trimroll, lof;
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	/*
274*7c478bd9Sstevel@tonic-gate 	 * remember location of youngest rolled delta
275*7c478bd9Sstevel@tonic-gate 	 */
276*7c478bd9Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
277*7c478bd9Sstevel@tonic-gate 	ul = mtm->mtm_ul;
278*7c478bd9Sstevel@tonic-gate 	head = ul->un_head_lof;
279*7c478bd9Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
280*7c478bd9Sstevel@tonic-gate 	for (me = age; me; me = me->me_agenext) {
281*7c478bd9Sstevel@tonic-gate 		lof = me->me_lof;
282*7c478bd9Sstevel@tonic-gate 		if (trimroll == 0)
283*7c478bd9Sstevel@tonic-gate 			trimroll = lof;
284*7c478bd9Sstevel@tonic-gate 		if (lof >= head) {
285*7c478bd9Sstevel@tonic-gate 			if (trimroll >= head && trimroll <= lof)
286*7c478bd9Sstevel@tonic-gate 				trimroll = lof;
287*7c478bd9Sstevel@tonic-gate 		} else {
288*7c478bd9Sstevel@tonic-gate 			if (trimroll <= lof || trimroll >= head)
289*7c478bd9Sstevel@tonic-gate 				trimroll = lof;
290*7c478bd9Sstevel@tonic-gate 		}
291*7c478bd9Sstevel@tonic-gate 	}
292*7c478bd9Sstevel@tonic-gate 	mtm->mtm_trimrlof = trimroll;
293*7c478bd9Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
294*7c478bd9Sstevel@tonic-gate 	return (1);
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate /*
298*7c478bd9Sstevel@tonic-gate  * scan test support
299*7c478bd9Sstevel@tonic-gate  */
300*7c478bd9Sstevel@tonic-gate int
301*7c478bd9Sstevel@tonic-gate logmap_logscan_commit_debug(off_t lof, mt_map_t *mtm)
302*7c478bd9Sstevel@tonic-gate {
303*7c478bd9Sstevel@tonic-gate 	off_t	oldtrimc, newtrimc, trimroll;
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 	trimroll = mtm->mtm_trimrlof;
306*7c478bd9Sstevel@tonic-gate 	oldtrimc = mtm->mtm_trimclof;
307*7c478bd9Sstevel@tonic-gate 	newtrimc = mtm->mtm_trimclof = dbtob(btod(lof));
308*7c478bd9Sstevel@tonic-gate 
309*7c478bd9Sstevel@tonic-gate 	/*
310*7c478bd9Sstevel@tonic-gate 	 * can't trim prior to transaction w/rolled delta
311*7c478bd9Sstevel@tonic-gate 	 */
312*7c478bd9Sstevel@tonic-gate 	if (trimroll)
313*7c478bd9Sstevel@tonic-gate 		if (newtrimc >= oldtrimc) {
314*7c478bd9Sstevel@tonic-gate 			if (trimroll <= newtrimc && trimroll >= oldtrimc)
315*7c478bd9Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
316*7c478bd9Sstevel@tonic-gate 		} else {
317*7c478bd9Sstevel@tonic-gate 			if (trimroll >= oldtrimc || trimroll <= newtrimc)
318*7c478bd9Sstevel@tonic-gate 				mtm->mtm_trimalof = newtrimc;
319*7c478bd9Sstevel@tonic-gate 		}
320*7c478bd9Sstevel@tonic-gate 	return (1);
321*7c478bd9Sstevel@tonic-gate }
322*7c478bd9Sstevel@tonic-gate 
323*7c478bd9Sstevel@tonic-gate int
324*7c478bd9Sstevel@tonic-gate logmap_logscan_add_debug(struct delta *dp, mt_map_t *mtm)
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate 	if ((dp->d_typ == DT_AB) || (dp->d_typ == DT_INODE))
327*7c478bd9Sstevel@tonic-gate 		mtm->mtm_trimalof = mtm->mtm_trimclof;
328*7c478bd9Sstevel@tonic-gate 	return (1);
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate 
331*7c478bd9Sstevel@tonic-gate /*
332*7c478bd9Sstevel@tonic-gate  * log-read after log-write
333*7c478bd9Sstevel@tonic-gate  */
334*7c478bd9Sstevel@tonic-gate int
335*7c478bd9Sstevel@tonic-gate map_check_ldl_write(ml_unit_t *ul, caddr_t va, offset_t vamof, mapentry_t *me)
336*7c478bd9Sstevel@tonic-gate {
337*7c478bd9Sstevel@tonic-gate 	caddr_t		bufp;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	ASSERT(me->me_nb);
340*7c478bd9Sstevel@tonic-gate 	ASSERT((me->me_flags & ME_AGE) == 0);
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	/* Alloc a buf */
343*7c478bd9Sstevel@tonic-gate 	bufp = kmem_alloc(me->me_nb, KM_SLEEP);
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	/* Do the read */
346*7c478bd9Sstevel@tonic-gate 	me->me_agenext = NULL;
347*7c478bd9Sstevel@tonic-gate 	if (ldl_read(ul, bufp, me->me_mof, me->me_nb, me) == 0) {
348*7c478bd9Sstevel@tonic-gate 		ASSERT(bcmp(bufp, va + (me->me_mof - vamof), me->me_nb) == 0);
349*7c478bd9Sstevel@tonic-gate 	}
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	kmem_free(bufp, me->me_nb);
352*7c478bd9Sstevel@tonic-gate 	return (1);
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate /*
356*7c478bd9Sstevel@tonic-gate  * Cleanup a map struct
357*7c478bd9Sstevel@tonic-gate  */
358*7c478bd9Sstevel@tonic-gate int
359*7c478bd9Sstevel@tonic-gate map_put_debug(mt_map_t *mtm)
360*7c478bd9Sstevel@tonic-gate {
361*7c478bd9Sstevel@tonic-gate 	struct topstats_link	*tsl, **ptsl;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	if (mtm->mtm_tops == NULL)
364*7c478bd9Sstevel@tonic-gate 		return (1);
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	/* Don't free this, cause the next snarf will want it */
367*7c478bd9Sstevel@tonic-gate 	if ((lufs_debug & MT_TRANSACT) != 0)
368*7c478bd9Sstevel@tonic-gate 		return (1);
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	ptsl = &topstats_anchor;
371*7c478bd9Sstevel@tonic-gate 	tsl = topstats_anchor;
372*7c478bd9Sstevel@tonic-gate 	while (tsl) {
373*7c478bd9Sstevel@tonic-gate 		if (mtm->mtm_tops == &tsl->ts_stats) {
374*7c478bd9Sstevel@tonic-gate 			mtm->mtm_tops = NULL;
375*7c478bd9Sstevel@tonic-gate 			*ptsl = tsl->ts_next;
376*7c478bd9Sstevel@tonic-gate 			kmem_free(tsl, sizeof (*tsl));
377*7c478bd9Sstevel@tonic-gate 			return (1);
378*7c478bd9Sstevel@tonic-gate 		}
379*7c478bd9Sstevel@tonic-gate 		ptsl = &tsl->ts_next;
380*7c478bd9Sstevel@tonic-gate 		tsl = tsl->ts_next;
381*7c478bd9Sstevel@tonic-gate 	}
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	return (1);
384*7c478bd9Sstevel@tonic-gate }
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate int
387*7c478bd9Sstevel@tonic-gate map_get_debug(ml_unit_t *ul, mt_map_t *mtm)
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate 	struct topstats_link	*tsl;
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	if ((ul->un_debug & MT_TRANSACT) == 0)
392*7c478bd9Sstevel@tonic-gate 		return (1);
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	if (mtm->mtm_type != logmaptype)
395*7c478bd9Sstevel@tonic-gate 		return (1);
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	tsl = topstats_anchor;
398*7c478bd9Sstevel@tonic-gate 	while (tsl) {
399*7c478bd9Sstevel@tonic-gate 		if (tsl->ts_dev == ul->un_dev) {
400*7c478bd9Sstevel@tonic-gate 			mtm->mtm_tops = &(tsl->ts_stats);
401*7c478bd9Sstevel@tonic-gate 			return (1);
402*7c478bd9Sstevel@tonic-gate 		}
403*7c478bd9Sstevel@tonic-gate 		tsl = tsl->ts_next;
404*7c478bd9Sstevel@tonic-gate 	}
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	tsl = kmem_zalloc(sizeof (*tsl), KM_SLEEP);
407*7c478bd9Sstevel@tonic-gate 	tsl->ts_dev = ul->un_dev;
408*7c478bd9Sstevel@tonic-gate 	tsl->ts_next = topstats_anchor;
409*7c478bd9Sstevel@tonic-gate 	topstats_anchor = tsl;
410*7c478bd9Sstevel@tonic-gate 	mtm->mtm_tops = &tsl->ts_stats;
411*7c478bd9Sstevel@tonic-gate 	return (1);
412*7c478bd9Sstevel@tonic-gate }
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate /*
415*7c478bd9Sstevel@tonic-gate  * check a map's list
416*7c478bd9Sstevel@tonic-gate  */
417*7c478bd9Sstevel@tonic-gate int
418*7c478bd9Sstevel@tonic-gate map_check_linkage(mt_map_t *mtm)
419*7c478bd9Sstevel@tonic-gate {
420*7c478bd9Sstevel@tonic-gate 	int		i;
421*7c478bd9Sstevel@tonic-gate 	int		hashed;
422*7c478bd9Sstevel@tonic-gate 	int		nexted;
423*7c478bd9Sstevel@tonic-gate 	int		preved;
424*7c478bd9Sstevel@tonic-gate 	int		ncancel;
425*7c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
426*7c478bd9Sstevel@tonic-gate 	off_t		olof;
427*7c478bd9Sstevel@tonic-gate 	off_t		firstlof;
428*7c478bd9Sstevel@tonic-gate 	int		wrapped;
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	mutex_enter(&mtm->mtm_mutex);
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate 	ASSERT(mtm->mtm_nme >= 0);
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate 	/*
435*7c478bd9Sstevel@tonic-gate 	 * verify the entries on the hash
436*7c478bd9Sstevel@tonic-gate 	 */
437*7c478bd9Sstevel@tonic-gate 	hashed = 0;
438*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < mtm->mtm_nhash; ++i) {
439*7c478bd9Sstevel@tonic-gate 		for (me = *(mtm->mtm_hash+i); me; me = me->me_hash) {
440*7c478bd9Sstevel@tonic-gate 			++hashed;
441*7c478bd9Sstevel@tonic-gate 			ASSERT(me->me_flags & ME_HASH);
442*7c478bd9Sstevel@tonic-gate 			ASSERT((me->me_flags & ME_LIST) == 0);
443*7c478bd9Sstevel@tonic-gate 		}
444*7c478bd9Sstevel@tonic-gate 	}
445*7c478bd9Sstevel@tonic-gate 	ASSERT(hashed >= mtm->mtm_nme);
446*7c478bd9Sstevel@tonic-gate 	/*
447*7c478bd9Sstevel@tonic-gate 	 * verify the doubly linked list of all entries
448*7c478bd9Sstevel@tonic-gate 	 */
449*7c478bd9Sstevel@tonic-gate 	nexted = 0;
450*7c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_next; me != (mapentry_t *)mtm; me = me->me_next)
451*7c478bd9Sstevel@tonic-gate 		nexted++;
452*7c478bd9Sstevel@tonic-gate 	preved = 0;
453*7c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_prev; me != (mapentry_t *)mtm; me = me->me_prev)
454*7c478bd9Sstevel@tonic-gate 		preved++;
455*7c478bd9Sstevel@tonic-gate 	ASSERT(nexted == preved);
456*7c478bd9Sstevel@tonic-gate 	ASSERT(nexted == hashed);
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 	/*
459*7c478bd9Sstevel@tonic-gate 	 * verify the cancel list
460*7c478bd9Sstevel@tonic-gate 	 */
461*7c478bd9Sstevel@tonic-gate 	ncancel = 0;
462*7c478bd9Sstevel@tonic-gate 	for (me = mtm->mtm_cancel; me; me = me->me_cancel) {
463*7c478bd9Sstevel@tonic-gate 		++ncancel;
464*7c478bd9Sstevel@tonic-gate 		ASSERT(me->me_flags & ME_CANCEL);
465*7c478bd9Sstevel@tonic-gate 	}
466*7c478bd9Sstevel@tonic-gate 	/*
467*7c478bd9Sstevel@tonic-gate 	 * verify the logmap's log offsets
468*7c478bd9Sstevel@tonic-gate 	 */
469*7c478bd9Sstevel@tonic-gate 	if (mtm->mtm_type == logmaptype) {
470*7c478bd9Sstevel@tonic-gate 		olof = mtm->mtm_next->me_lof;
471*7c478bd9Sstevel@tonic-gate 		firstlof = olof;
472*7c478bd9Sstevel@tonic-gate 		wrapped = 0;
473*7c478bd9Sstevel@tonic-gate 		/*
474*7c478bd9Sstevel@tonic-gate 		 * Make sure to skip any mapentries whose me_lof = 0
475*7c478bd9Sstevel@tonic-gate 		 * and me_type == DT_CANCEL, these are mapentries
476*7c478bd9Sstevel@tonic-gate 		 * in place just to mark user block deletions as not
477*7c478bd9Sstevel@tonic-gate 		 * available for allocate within the same moby transaction
478*7c478bd9Sstevel@tonic-gate 		 * in case we crash before it is comitted.  Skip these
479*7c478bd9Sstevel@tonic-gate 		 * entries in the checks below as they are not applicable.
480*7c478bd9Sstevel@tonic-gate 		 */
481*7c478bd9Sstevel@tonic-gate 		for (me = mtm->mtm_next->me_next;
482*7c478bd9Sstevel@tonic-gate 		    me != (mapentry_t *)mtm;
483*7c478bd9Sstevel@tonic-gate 		    me = me->me_next) {
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 			if (me->me_lof == 0 && me->me_dt == DT_CANCEL)
486*7c478bd9Sstevel@tonic-gate 				continue;
487*7c478bd9Sstevel@tonic-gate 			if (firstlof == 0) {
488*7c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
489*7c478bd9Sstevel@tonic-gate 				firstlof = olof;
490*7c478bd9Sstevel@tonic-gate 				if (me->me_next != (mapentry_t *)mtm)
491*7c478bd9Sstevel@tonic-gate 					me = me->me_next;
492*7c478bd9Sstevel@tonic-gate 				continue;
493*7c478bd9Sstevel@tonic-gate 			}
494*7c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof != olof);
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate 			if (wrapped) {
497*7c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof > olof);
498*7c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
499*7c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
500*7c478bd9Sstevel@tonic-gate 				continue;
501*7c478bd9Sstevel@tonic-gate 			}
502*7c478bd9Sstevel@tonic-gate 			if (me->me_lof < olof) {
503*7c478bd9Sstevel@tonic-gate 				ASSERT(me->me_lof < firstlof);
504*7c478bd9Sstevel@tonic-gate 				wrapped = 1;
505*7c478bd9Sstevel@tonic-gate 				olof = me->me_lof;
506*7c478bd9Sstevel@tonic-gate 				continue;
507*7c478bd9Sstevel@tonic-gate 			}
508*7c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof > firstlof);
509*7c478bd9Sstevel@tonic-gate 			ASSERT(me->me_lof < mtm->mtm_ul->un_eol_lof);
510*7c478bd9Sstevel@tonic-gate 			olof = me->me_lof;
511*7c478bd9Sstevel@tonic-gate 		}
512*7c478bd9Sstevel@tonic-gate 	}
513*7c478bd9Sstevel@tonic-gate 
514*7c478bd9Sstevel@tonic-gate 	mutex_exit(&mtm->mtm_mutex);
515*7c478bd9Sstevel@tonic-gate 	return (1);
516*7c478bd9Sstevel@tonic-gate }
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate /*
519*7c478bd9Sstevel@tonic-gate  * check for overlap
520*7c478bd9Sstevel@tonic-gate  */
521*7c478bd9Sstevel@tonic-gate int
522*7c478bd9Sstevel@tonic-gate matamap_overlap(mt_map_t *mtm, offset_t mof, off_t nb)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	off_t		hnb;
525*7c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
526*7c478bd9Sstevel@tonic-gate 	mapentry_t	**mep;
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	for (hnb = 0; nb; nb -= hnb, mof += hnb) {
529*7c478bd9Sstevel@tonic-gate 
530*7c478bd9Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
531*7c478bd9Sstevel@tonic-gate 		if (hnb > nb)
532*7c478bd9Sstevel@tonic-gate 			hnb = nb;
533*7c478bd9Sstevel@tonic-gate 		/*
534*7c478bd9Sstevel@tonic-gate 		 * search for dup entry
535*7c478bd9Sstevel@tonic-gate 		 */
536*7c478bd9Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
537*7c478bd9Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
538*7c478bd9Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
539*7c478bd9Sstevel@tonic-gate 			if (DATAoverlapME(mof, hnb, me))
540*7c478bd9Sstevel@tonic-gate 				break;
541*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 		/*
544*7c478bd9Sstevel@tonic-gate 		 * overlap detected
545*7c478bd9Sstevel@tonic-gate 		 */
546*7c478bd9Sstevel@tonic-gate 		if (me)
547*7c478bd9Sstevel@tonic-gate 			return (1);
548*7c478bd9Sstevel@tonic-gate 	}
549*7c478bd9Sstevel@tonic-gate 	return (0);
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate /*
552*7c478bd9Sstevel@tonic-gate  * check for within
553*7c478bd9Sstevel@tonic-gate  */
554*7c478bd9Sstevel@tonic-gate int
555*7c478bd9Sstevel@tonic-gate matamap_within(mt_map_t *mtm, offset_t mof, off_t nb)
556*7c478bd9Sstevel@tonic-gate {
557*7c478bd9Sstevel@tonic-gate 	off_t		hnb;
558*7c478bd9Sstevel@tonic-gate 	mapentry_t	*me;
559*7c478bd9Sstevel@tonic-gate 	mapentry_t	**mep;
560*7c478bd9Sstevel@tonic-gate 	int		scans	= 0;
561*7c478bd9Sstevel@tonic-gate 	int		withins	= 0;
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 	for (hnb = 0; nb && scans == withins; nb -= hnb, mof += hnb) {
564*7c478bd9Sstevel@tonic-gate 		scans++;
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 		hnb = MAPBLOCKSIZE - (mof & MAPBLOCKOFF);
567*7c478bd9Sstevel@tonic-gate 		if (hnb > nb)
568*7c478bd9Sstevel@tonic-gate 			hnb = nb;
569*7c478bd9Sstevel@tonic-gate 		/*
570*7c478bd9Sstevel@tonic-gate 		 * search for within entry
571*7c478bd9Sstevel@tonic-gate 		 */
572*7c478bd9Sstevel@tonic-gate 		mep = MAP_HASH(mof, mtm);
573*7c478bd9Sstevel@tonic-gate 		mutex_enter(&mtm->mtm_mutex);
574*7c478bd9Sstevel@tonic-gate 		for (me = *mep; me; me = me->me_hash)
575*7c478bd9Sstevel@tonic-gate 			if (DATAwithinME(mof, hnb, me)) {
576*7c478bd9Sstevel@tonic-gate 				withins++;
577*7c478bd9Sstevel@tonic-gate 				break;
578*7c478bd9Sstevel@tonic-gate 			}
579*7c478bd9Sstevel@tonic-gate 		mutex_exit(&mtm->mtm_mutex);
580*7c478bd9Sstevel@tonic-gate 	}
581*7c478bd9Sstevel@tonic-gate 	return (scans == withins);
582*7c478bd9Sstevel@tonic-gate }
583*7c478bd9Sstevel@tonic-gate 
584*7c478bd9Sstevel@tonic-gate int
585*7c478bd9Sstevel@tonic-gate ldl_sethead_debug(ml_unit_t *ul)
586*7c478bd9Sstevel@tonic-gate {
587*7c478bd9Sstevel@tonic-gate 	mt_map_t	*mtm	= ul->un_logmap;
588*7c478bd9Sstevel@tonic-gate 	off_t		trimr	= mtm->mtm_trimrlof;
589*7c478bd9Sstevel@tonic-gate 	off_t		head	= ul->un_head_lof;
590*7c478bd9Sstevel@tonic-gate 	off_t		tail	= ul->un_tail_lof;
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 	if (head <= tail) {
593*7c478bd9Sstevel@tonic-gate 		if (trimr < head || trimr >= tail)
594*7c478bd9Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
595*7c478bd9Sstevel@tonic-gate 	} else {
596*7c478bd9Sstevel@tonic-gate 		if (trimr >= tail && trimr < head)
597*7c478bd9Sstevel@tonic-gate 			mtm->mtm_trimrlof = 0;
598*7c478bd9Sstevel@tonic-gate 	}
599*7c478bd9Sstevel@tonic-gate 	return (1);
600*7c478bd9Sstevel@tonic-gate }
601*7c478bd9Sstevel@tonic-gate 
602*7c478bd9Sstevel@tonic-gate int
603*7c478bd9Sstevel@tonic-gate lufs_initialize_debug(ml_odunit_t *ud)
604*7c478bd9Sstevel@tonic-gate {
605*7c478bd9Sstevel@tonic-gate 	ud->od_debug = lufs_debug;
606*7c478bd9Sstevel@tonic-gate 	return (1);
607*7c478bd9Sstevel@tonic-gate }
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate /*
612*7c478bd9Sstevel@tonic-gate  * lufs_debug controls the debug level for TSufs, and is only used
613*7c478bd9Sstevel@tonic-gate  * for a debug kernel. It's referenced by ufs_ioctl() and so is
614*7c478bd9Sstevel@tonic-gate  * not under #ifdef DEBUG compilation.
615*7c478bd9Sstevel@tonic-gate  */
616*7c478bd9Sstevel@tonic-gate uint_t lufs_debug;
617