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