1*1619Ssjelinek /*
2*1619Ssjelinek * CDDL HEADER START
3*1619Ssjelinek *
4*1619Ssjelinek * The contents of this file are subject to the terms of the
5*1619Ssjelinek * Common Development and Distribution License (the "License").
6*1619Ssjelinek * You may not use this file except in compliance with the License.
7*1619Ssjelinek *
8*1619Ssjelinek * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1619Ssjelinek * or http://www.opensolaris.org/os/licensing.
10*1619Ssjelinek * See the License for the specific language governing permissions
11*1619Ssjelinek * and limitations under the License.
12*1619Ssjelinek *
13*1619Ssjelinek * When distributing Covered Code, include this CDDL HEADER in each
14*1619Ssjelinek * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1619Ssjelinek * If applicable, add the following below this CDDL HEADER, with the
16*1619Ssjelinek * fields enclosed by brackets "[]" replaced with your own identifying
17*1619Ssjelinek * information: Portions Copyright [yyyy] [name of copyright owner]
18*1619Ssjelinek *
19*1619Ssjelinek * CDDL HEADER END
20*1619Ssjelinek */
21*1619Ssjelinek /*
22*1619Ssjelinek * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*1619Ssjelinek * Use is subject to license terms.
24*1619Ssjelinek */
25*1619Ssjelinek
26*1619Ssjelinek #pragma ident "%Z%%M% %I% %E% SMI"
27*1619Ssjelinek
28*1619Ssjelinek #include <mdb/mdb_modapi.h>
29*1619Ssjelinek
30*1619Ssjelinek #include <sys/types.h>
31*1619Ssjelinek #include <sys/uio.h>
32*1619Ssjelinek #include <sys/vnode.h>
33*1619Ssjelinek #include <sys/fs/ufs_log.h>
34*1619Ssjelinek #include "ufs_cmds.h"
35*1619Ssjelinek
36*1619Ssjelinek
37*1619Ssjelinek typedef struct ufslogmap_walk_data {
38*1619Ssjelinek mapentry_t me;
39*1619Ssjelinek mapentry_t *start_addr;
40*1619Ssjelinek mapentry_t *prev_addr;
41*1619Ssjelinek } ufslogmap_walk_data_t;
42*1619Ssjelinek
43*1619Ssjelinek /*
44*1619Ssjelinek * Ensure we are started with a user specified address.
45*1619Ssjelinek * We also allocate a ufslogmap_walk_data_t for storage,
46*1619Ssjelinek * and save this using the walk_data pointer.
47*1619Ssjelinek */
48*1619Ssjelinek int
ufslogmap_walk_init(mdb_walk_state_t * wsp)49*1619Ssjelinek ufslogmap_walk_init(mdb_walk_state_t *wsp)
50*1619Ssjelinek {
51*1619Ssjelinek ufslogmap_walk_data_t *uw;
52*1619Ssjelinek
53*1619Ssjelinek if (wsp->walk_addr == NULL) {
54*1619Ssjelinek mdb_warn("must specify an address\n");
55*1619Ssjelinek return (WALK_ERR);
56*1619Ssjelinek }
57*1619Ssjelinek
58*1619Ssjelinek uw = mdb_zalloc(sizeof (ufslogmap_walk_data_t), UM_SLEEP | UM_GC);
59*1619Ssjelinek
60*1619Ssjelinek uw->start_addr = (mapentry_t *)wsp->walk_addr;
61*1619Ssjelinek wsp->walk_data = uw;
62*1619Ssjelinek return (WALK_NEXT);
63*1619Ssjelinek }
64*1619Ssjelinek
65*1619Ssjelinek /*
66*1619Ssjelinek * Routine to step through one element of the list.
67*1619Ssjelinek */
68*1619Ssjelinek int
ufslogmap_walk_step(mdb_walk_state_t * wsp)69*1619Ssjelinek ufslogmap_walk_step(mdb_walk_state_t *wsp)
70*1619Ssjelinek {
71*1619Ssjelinek ufslogmap_walk_data_t *uw = wsp->walk_data;
72*1619Ssjelinek uintptr_t walk_addr = wsp->walk_addr;
73*1619Ssjelinek
74*1619Ssjelinek /*
75*1619Ssjelinek * Read the mapentry at the current walk address
76*1619Ssjelinek */
77*1619Ssjelinek if (mdb_vread(&uw->me, sizeof (mapentry_t), walk_addr) == -1) {
78*1619Ssjelinek mdb_warn("failed to read mapentry_t at %p", walk_addr);
79*1619Ssjelinek return (WALK_DONE);
80*1619Ssjelinek }
81*1619Ssjelinek
82*1619Ssjelinek /*
83*1619Ssjelinek * Check for empty list.
84*1619Ssjelinek */
85*1619Ssjelinek if (uw->me.me_next == uw->me.me_prev) {
86*1619Ssjelinek return (WALK_DONE);
87*1619Ssjelinek }
88*1619Ssjelinek
89*1619Ssjelinek /*
90*1619Ssjelinek * Check for end of list.
91*1619Ssjelinek */
92*1619Ssjelinek if (uw->me.me_next == uw->start_addr) {
93*1619Ssjelinek return (WALK_DONE);
94*1619Ssjelinek }
95*1619Ssjelinek
96*1619Ssjelinek /*
97*1619Ssjelinek * Check for proper linkage
98*1619Ssjelinek */
99*1619Ssjelinek if (uw->prev_addr && (uw->me.me_prev != uw->prev_addr)) {
100*1619Ssjelinek mdb_warn("invalid linkage mapentry_t at %p", walk_addr);
101*1619Ssjelinek return (WALK_DONE);
102*1619Ssjelinek }
103*1619Ssjelinek uw->prev_addr = (mapentry_t *)walk_addr;
104*1619Ssjelinek
105*1619Ssjelinek /*
106*1619Ssjelinek * Save next address and call callback with current address
107*1619Ssjelinek */
108*1619Ssjelinek wsp->walk_addr = (uintptr_t)uw->me.me_next;
109*1619Ssjelinek return (wsp->walk_callback(walk_addr, wsp->walk_data,
110*1619Ssjelinek wsp->walk_cbdata));
111*1619Ssjelinek }
112*1619Ssjelinek
113*1619Ssjelinek static const char *
delta2str(delta_t delta_type)114*1619Ssjelinek delta2str(delta_t delta_type)
115*1619Ssjelinek {
116*1619Ssjelinek switch (delta_type) {
117*1619Ssjelinek case DT_NONE: return ("none");
118*1619Ssjelinek case DT_SB: return ("sb");
119*1619Ssjelinek case DT_CG: return ("cg");
120*1619Ssjelinek case DT_SI: return ("si");
121*1619Ssjelinek case DT_AB: return ("ab");
122*1619Ssjelinek case DT_ABZERO: return ("abzero");
123*1619Ssjelinek case DT_DIR: return ("dir");
124*1619Ssjelinek case DT_INODE: return ("inode");
125*1619Ssjelinek case DT_FBI: return ("fbi");
126*1619Ssjelinek case DT_QR: return ("quota");
127*1619Ssjelinek case DT_COMMIT: return ("commit");
128*1619Ssjelinek case DT_CANCEL: return ("cancel");
129*1619Ssjelinek case DT_BOT: return ("trans");
130*1619Ssjelinek case DT_EOT: return ("etrans");
131*1619Ssjelinek case DT_UD: return ("udata");
132*1619Ssjelinek case DT_SUD: return ("sudata");
133*1619Ssjelinek case DT_SHAD: return ("shadow");
134*1619Ssjelinek default: return ("???");
135*1619Ssjelinek }
136*1619Ssjelinek }
137*1619Ssjelinek
138*1619Ssjelinek /* ARGSUSED */
139*1619Ssjelinek int
mapentry_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)140*1619Ssjelinek mapentry_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
141*1619Ssjelinek {
142*1619Ssjelinek mapentry_t me;
143*1619Ssjelinek
144*1619Ssjelinek if (!(flags & DCMD_ADDRSPEC))
145*1619Ssjelinek return (DCMD_USAGE);
146*1619Ssjelinek
147*1619Ssjelinek if (DCMD_HDRSPEC(flags)) {
148*1619Ssjelinek mdb_printf("%<u>%?s %6s %8s %8s %s%</u>\n",
149*1619Ssjelinek "ADDR", "TYPE", "SIZE", "TRANS", "HANDLER");
150*1619Ssjelinek }
151*1619Ssjelinek
152*1619Ssjelinek if (mdb_vread(&me, sizeof (me), addr) == -1) {
153*1619Ssjelinek mdb_warn("couldn't read ufslog mapentry at %p", addr);
154*1619Ssjelinek return (DCMD_ABORT);
155*1619Ssjelinek }
156*1619Ssjelinek
157*1619Ssjelinek /*
158*1619Ssjelinek * Validate mapentry
159*1619Ssjelinek */
160*1619Ssjelinek if (me.me_delta.d_typ >= DT_MAX) {
161*1619Ssjelinek mdb_warn("Invalid delta type for mapentry at %p", addr);
162*1619Ssjelinek return (DCMD_ABORT);
163*1619Ssjelinek }
164*1619Ssjelinek
165*1619Ssjelinek mdb_printf("%0?p %6s %8x %8x %a\n",
166*1619Ssjelinek addr,
167*1619Ssjelinek delta2str(me.me_delta.d_typ),
168*1619Ssjelinek me.me_delta.d_nb,
169*1619Ssjelinek me.me_tid,
170*1619Ssjelinek me.me_func);
171*1619Ssjelinek
172*1619Ssjelinek return (DCMD_OK);
173*1619Ssjelinek }
174*1619Ssjelinek
175*1619Ssjelinek typedef struct {
176*1619Ssjelinek uint64_t nentries; /* number of mapentries */
177*1619Ssjelinek uint64_t totalsize; /* total number of bytes */
178*1619Ssjelinek uint32_t transid; /* first transaction id */
179*1619Ssjelinek int transdiff; /* transaction different */
180*1619Ssjelinek uint32_t delta_cnt[DT_MAX]; /* count of each delta */
181*1619Ssjelinek uint64_t delta_sum[DT_MAX]; /* total number of bytes for delta */
182*1619Ssjelinek } mapstats_t;
183*1619Ssjelinek
184*1619Ssjelinek /* ARGSUSED */
185*1619Ssjelinek int
mapadd(uintptr_t * addr,ufslogmap_walk_data_t * uw,mapstats_t * msp)186*1619Ssjelinek mapadd(uintptr_t *addr, ufslogmap_walk_data_t *uw, mapstats_t *msp)
187*1619Ssjelinek {
188*1619Ssjelinek if (msp->nentries == 0) {
189*1619Ssjelinek msp->transid = uw->me.me_tid;
190*1619Ssjelinek } else {
191*1619Ssjelinek if (msp->transid != uw->me.me_tid) {
192*1619Ssjelinek msp->transdiff = TRUE;
193*1619Ssjelinek }
194*1619Ssjelinek }
195*1619Ssjelinek msp->nentries++;
196*1619Ssjelinek msp->totalsize += uw->me.me_nb;
197*1619Ssjelinek if (uw->me.me_dt >= DT_MAX) {
198*1619Ssjelinek mdb_warn("Invalid delta type for mapentry at %p", addr);
199*1619Ssjelinek } else {
200*1619Ssjelinek msp->delta_cnt[uw->me.me_dt]++;
201*1619Ssjelinek msp->delta_sum[uw->me.me_dt] += uw->me.me_nb;
202*1619Ssjelinek }
203*1619Ssjelinek return (WALK_NEXT);
204*1619Ssjelinek }
205*1619Ssjelinek
206*1619Ssjelinek /*ARGSUSED*/
207*1619Ssjelinek int
mapstats_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)208*1619Ssjelinek mapstats_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
209*1619Ssjelinek {
210*1619Ssjelinek mapstats_t *msp;
211*1619Ssjelinek int i;
212*1619Ssjelinek
213*1619Ssjelinek if (!(flags & DCMD_ADDRSPEC))
214*1619Ssjelinek return (DCMD_USAGE);
215*1619Ssjelinek
216*1619Ssjelinek msp = mdb_zalloc(sizeof (mapstats_t), UM_SLEEP | UM_GC);
217*1619Ssjelinek msp->transdiff = FALSE;
218*1619Ssjelinek
219*1619Ssjelinek if (mdb_pwalk("ufslogmap", (mdb_walk_cb_t)mapadd, msp, addr) == -1) {
220*1619Ssjelinek mdb_warn("can't walk ufslogmap for stats");
221*1619Ssjelinek return (DCMD_ERR);
222*1619Ssjelinek }
223*1619Ssjelinek
224*1619Ssjelinek mdb_printf("Number of entries 0x%llx\n", msp->nentries);
225*1619Ssjelinek mdb_printf("Total map size 0x%llx\n", msp->totalsize);
226*1619Ssjelinek if (msp->transdiff) {
227*1619Ssjelinek mdb_printf("Multiple transactions\n");
228*1619Ssjelinek } else {
229*1619Ssjelinek mdb_printf("All the same transaction id = %d\n", msp->transid);
230*1619Ssjelinek }
231*1619Ssjelinek if (msp->nentries) {
232*1619Ssjelinek mdb_printf("%<u>delta count(hex) avsize(hex)%</u>\n");
233*1619Ssjelinek for (i = 0; i < DT_MAX; i++) {
234*1619Ssjelinek if (msp->delta_cnt[i]) {
235*1619Ssjelinek mdb_printf("%6s %10X %10X\n",
236*1619Ssjelinek delta2str(i), msp->delta_cnt[i],
237*1619Ssjelinek msp->delta_sum[i] / msp->delta_cnt[i]);
238*1619Ssjelinek }
239*1619Ssjelinek }
240*1619Ssjelinek }
241*1619Ssjelinek return (DCMD_OK);
242*1619Ssjelinek }
243