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