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