zdb_il.c revision 168404
1168404Spjd/*
2168404Spjd * CDDL HEADER START
3168404Spjd *
4168404Spjd * The contents of this file are subject to the terms of the
5168404Spjd * Common Development and Distribution License (the "License").
6168404Spjd * You may not use this file except in compliance with the License.
7168404Spjd *
8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9168404Spjd * or http://www.opensolaris.org/os/licensing.
10168404Spjd * See the License for the specific language governing permissions
11168404Spjd * and limitations under the License.
12168404Spjd *
13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each
14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15168404Spjd * If applicable, add the following below this CDDL HEADER, with the
16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying
17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner]
18168404Spjd *
19168404Spjd * CDDL HEADER END
20168404Spjd */
21168404Spjd/*
22168404Spjd * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23168404Spjd * Use is subject to license terms.
24168404Spjd */
25168404Spjd
26168404Spjd#pragma ident	"%Z%%M%	%I%	%E% SMI"
27168404Spjd
28168404Spjd/*
29168404Spjd * Print intent log header and statistics.
30168404Spjd */
31168404Spjd
32168404Spjd#include <stdio.h>
33168404Spjd#include <stdlib.h>
34168404Spjd#include <ctype.h>
35168404Spjd#include <sys/zfs_context.h>
36168404Spjd#include <sys/spa.h>
37168404Spjd#include <sys/dmu.h>
38168404Spjd#include <sys/stat.h>
39168404Spjd#include <sys/resource.h>
40168404Spjd#include <sys/zil.h>
41168404Spjd#include <sys/zil_impl.h>
42168404Spjd
43168404Spjdextern uint8_t dump_opt[256];
44168404Spjd
45168404Spjdstatic void
46168404Spjdprint_log_bp(const blkptr_t *bp, const char *prefix)
47168404Spjd{
48168404Spjd	char blkbuf[BP_SPRINTF_LEN];
49168404Spjd
50168404Spjd	sprintf_blkptr(blkbuf, BP_SPRINTF_LEN, bp);
51168404Spjd	(void) printf("%s%s\n", prefix, blkbuf);
52168404Spjd}
53168404Spjd
54168404Spjd/* ARGSUSED */
55168404Spjdstatic void
56168404Spjdzil_prt_rec_create(zilog_t *zilog, int txtype, lr_create_t *lr)
57168404Spjd{
58168404Spjd	time_t crtime = lr->lr_crtime[0];
59168404Spjd	char *name = (char *)(lr + 1);
60168404Spjd	char *link = name + strlen(name) + 1;
61168404Spjd
62168404Spjd	if (txtype == TX_SYMLINK)
63168404Spjd		(void) printf("\t\t\t%s -> %s\n", name, link);
64168404Spjd	else
65168404Spjd		(void) printf("\t\t\t%s\n", name);
66168404Spjd
67168404Spjd	(void) printf("\t\t\t%s", ctime(&crtime));
68168404Spjd	(void) printf("\t\t\tdoid %llu, foid %llu, mode %llo\n",
69168404Spjd	    (u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_foid,
70168404Spjd	    (longlong_t)lr->lr_mode);
71168404Spjd	(void) printf("\t\t\tuid %llu, gid %llu, gen %llu, rdev 0x%llx\n",
72168404Spjd	    (u_longlong_t)lr->lr_uid, (u_longlong_t)lr->lr_gid,
73168404Spjd	    (u_longlong_t)lr->lr_gen, (u_longlong_t)lr->lr_rdev);
74168404Spjd}
75168404Spjd
76168404Spjd/* ARGSUSED */
77168404Spjdstatic void
78168404Spjdzil_prt_rec_remove(zilog_t *zilog, int txtype, lr_remove_t *lr)
79168404Spjd{
80168404Spjd	(void) printf("\t\t\tdoid %llu, name %s\n",
81168404Spjd	    (u_longlong_t)lr->lr_doid, (char *)(lr + 1));
82168404Spjd}
83168404Spjd
84168404Spjd/* ARGSUSED */
85168404Spjdstatic void
86168404Spjdzil_prt_rec_link(zilog_t *zilog, int txtype, lr_link_t *lr)
87168404Spjd{
88168404Spjd	(void) printf("\t\t\tdoid %llu, link_obj %llu, name %s\n",
89168404Spjd	    (u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_link_obj,
90168404Spjd	    (char *)(lr + 1));
91168404Spjd}
92168404Spjd
93168404Spjd/* ARGSUSED */
94168404Spjdstatic void
95168404Spjdzil_prt_rec_rename(zilog_t *zilog, int txtype, lr_rename_t *lr)
96168404Spjd{
97168404Spjd	char *snm = (char *)(lr + 1);
98168404Spjd	char *tnm = snm + strlen(snm) + 1;
99168404Spjd
100168404Spjd	(void) printf("\t\t\tsdoid %llu, tdoid %llu\n",
101168404Spjd	    (u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid);
102168404Spjd	(void) printf("\t\t\tsrc %s tgt %s\n", snm, tnm);
103168404Spjd}
104168404Spjd
105168404Spjd/* ARGSUSED */
106168404Spjdstatic void
107168404Spjdzil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr)
108168404Spjd{
109168404Spjd	char *data, *dlimit;
110168404Spjd	blkptr_t *bp = &lr->lr_blkptr;
111168404Spjd	char buf[SPA_MAXBLOCKSIZE];
112168404Spjd	int verbose = MAX(dump_opt['d'], dump_opt['i']);
113168404Spjd	int error;
114168404Spjd
115168404Spjd	(void) printf("\t\t\tfoid %llu, offset 0x%llx,"
116168404Spjd	    " length 0x%llx, blkoff 0x%llx\n",
117168404Spjd	    (u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
118168404Spjd	    (u_longlong_t)lr->lr_length, (u_longlong_t)lr->lr_blkoff);
119168404Spjd
120168404Spjd	if (verbose < 5)
121168404Spjd		return;
122168404Spjd
123168404Spjd	if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) {
124168404Spjd		(void) printf("\t\t\thas blkptr, %s\n",
125168404Spjd		    bp->blk_birth >= spa_first_txg(zilog->zl_spa) ?
126168404Spjd		    "will claim" : "won't claim");
127168404Spjd		print_log_bp(bp, "\t\t\t");
128168404Spjd		if (bp->blk_birth == 0) {
129168404Spjd			bzero(buf, sizeof (buf));
130168404Spjd		} else {
131168404Spjd			zbookmark_t zb;
132168404Spjd
133168404Spjd			ASSERT3U(bp->blk_cksum.zc_word[ZIL_ZC_OBJSET], ==,
134168404Spjd			    dmu_objset_id(zilog->zl_os));
135168404Spjd
136168404Spjd			zb.zb_objset = bp->blk_cksum.zc_word[ZIL_ZC_OBJSET];
137168404Spjd			zb.zb_object = 0;
138168404Spjd			zb.zb_level = -1;
139168404Spjd			zb.zb_blkid = bp->blk_cksum.zc_word[ZIL_ZC_SEQ];
140168404Spjd
141168404Spjd			error = zio_wait(zio_read(NULL, zilog->zl_spa,
142168404Spjd			    bp, buf, BP_GET_LSIZE(bp), NULL, NULL,
143168404Spjd			    ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL, &zb));
144168404Spjd			if (error)
145168404Spjd				return;
146168404Spjd		}
147168404Spjd		data = buf + lr->lr_blkoff;
148168404Spjd	} else {
149168404Spjd		data = (char *)(lr + 1);
150168404Spjd	}
151168404Spjd
152168404Spjd	dlimit = data + MIN(lr->lr_length,
153168404Spjd	    (verbose < 6 ? 20 : SPA_MAXBLOCKSIZE));
154168404Spjd
155168404Spjd	(void) printf("\t\t\t");
156168404Spjd	while (data < dlimit) {
157168404Spjd		if (isprint(*data))
158168404Spjd			(void) printf("%c ", *data);
159168404Spjd		else
160168404Spjd			(void) printf("%2X", *data);
161168404Spjd		data++;
162168404Spjd	}
163168404Spjd	(void) printf("\n");
164168404Spjd}
165168404Spjd
166168404Spjd/* ARGSUSED */
167168404Spjdstatic void
168168404Spjdzil_prt_rec_truncate(zilog_t *zilog, int txtype, lr_truncate_t *lr)
169168404Spjd{
170168404Spjd	(void) printf("\t\t\tfoid %llu, offset 0x%llx, length 0x%llx\n",
171168404Spjd	    (u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset,
172168404Spjd	    (u_longlong_t)lr->lr_length);
173168404Spjd}
174168404Spjd
175168404Spjd/* ARGSUSED */
176168404Spjdstatic void
177168404Spjdzil_prt_rec_setattr(zilog_t *zilog, int txtype, lr_setattr_t *lr)
178168404Spjd{
179168404Spjd	time_t atime = (time_t)lr->lr_atime[0];
180168404Spjd	time_t mtime = (time_t)lr->lr_mtime[0];
181168404Spjd
182168404Spjd	(void) printf("\t\t\tfoid %llu, mask 0x%llx\n",
183168404Spjd	    (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_mask);
184168404Spjd
185168404Spjd	if (lr->lr_mask & AT_MODE) {
186168404Spjd		(void) printf("\t\t\tAT_MODE  %llo\n",
187168404Spjd		    (longlong_t)lr->lr_mode);
188168404Spjd	}
189168404Spjd
190168404Spjd	if (lr->lr_mask & AT_UID) {
191168404Spjd		(void) printf("\t\t\tAT_UID   %llu\n",
192168404Spjd		    (u_longlong_t)lr->lr_uid);
193168404Spjd	}
194168404Spjd
195168404Spjd	if (lr->lr_mask & AT_GID) {
196168404Spjd		(void) printf("\t\t\tAT_GID   %llu\n",
197168404Spjd		    (u_longlong_t)lr->lr_gid);
198168404Spjd	}
199168404Spjd
200168404Spjd	if (lr->lr_mask & AT_SIZE) {
201168404Spjd		(void) printf("\t\t\tAT_SIZE  %llu\n",
202168404Spjd		    (u_longlong_t)lr->lr_size);
203168404Spjd	}
204168404Spjd
205168404Spjd	if (lr->lr_mask & AT_ATIME) {
206168404Spjd		(void) printf("\t\t\tAT_ATIME %llu.%09llu %s",
207168404Spjd		    (u_longlong_t)lr->lr_atime[0],
208168404Spjd		    (u_longlong_t)lr->lr_atime[1],
209168404Spjd		    ctime(&atime));
210168404Spjd	}
211168404Spjd
212168404Spjd	if (lr->lr_mask & AT_MTIME) {
213168404Spjd		(void) printf("\t\t\tAT_MTIME %llu.%09llu %s",
214168404Spjd		    (u_longlong_t)lr->lr_mtime[0],
215168404Spjd		    (u_longlong_t)lr->lr_mtime[1],
216168404Spjd		    ctime(&mtime));
217168404Spjd	}
218168404Spjd}
219168404Spjd
220168404Spjd/* ARGSUSED */
221168404Spjdstatic void
222168404Spjdzil_prt_rec_acl(zilog_t *zilog, int txtype, lr_acl_t *lr)
223168404Spjd{
224168404Spjd	(void) printf("\t\t\tfoid %llu, aclcnt %llu\n",
225168404Spjd	    (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt);
226168404Spjd}
227168404Spjd
228168404Spjdtypedef void (*zil_prt_rec_func_t)();
229168404Spjdtypedef struct zil_rec_info {
230168404Spjd	zil_prt_rec_func_t	zri_print;
231168404Spjd	char			*zri_name;
232168404Spjd	uint64_t		zri_count;
233168404Spjd} zil_rec_info_t;
234168404Spjd
235168404Spjdstatic zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
236168404Spjd	{	NULL,			"Total      "	},
237168404Spjd	{	zil_prt_rec_create,	"TX_CREATE  "	},
238168404Spjd	{	zil_prt_rec_create,	"TX_MKDIR   "	},
239168404Spjd	{	zil_prt_rec_create,	"TX_MKXATTR "	},
240168404Spjd	{	zil_prt_rec_create,	"TX_SYMLINK "	},
241168404Spjd	{	zil_prt_rec_remove,	"TX_REMOVE  "	},
242168404Spjd	{	zil_prt_rec_remove,	"TX_RMDIR   "	},
243168404Spjd	{	zil_prt_rec_link,	"TX_LINK    "	},
244168404Spjd	{	zil_prt_rec_rename,	"TX_RENAME  "	},
245168404Spjd	{	zil_prt_rec_write,	"TX_WRITE   "	},
246168404Spjd	{	zil_prt_rec_truncate,	"TX_TRUNCATE"	},
247168404Spjd	{	zil_prt_rec_setattr,	"TX_SETATTR "	},
248168404Spjd	{	zil_prt_rec_acl,	"TX_ACL     "	},
249168404Spjd};
250168404Spjd
251168404Spjd/* ARGSUSED */
252168404Spjdstatic void
253168404Spjdprint_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
254168404Spjd{
255168404Spjd	int txtype;
256168404Spjd	int verbose = MAX(dump_opt['d'], dump_opt['i']);
257168404Spjd
258168404Spjd	txtype = lr->lrc_txtype;
259168404Spjd
260168404Spjd	ASSERT(txtype != 0 && (uint_t)txtype < TX_MAX_TYPE);
261168404Spjd	ASSERT(lr->lrc_txg);
262168404Spjd
263168404Spjd	(void) printf("\t\t%s len %6llu, txg %llu, seq %llu\n",
264168404Spjd	    zil_rec_info[txtype].zri_name,
265168404Spjd	    (u_longlong_t)lr->lrc_reclen,
266168404Spjd	    (u_longlong_t)lr->lrc_txg,
267168404Spjd	    (u_longlong_t)lr->lrc_seq);
268168404Spjd
269168404Spjd	if (txtype && verbose >= 3)
270168404Spjd		zil_rec_info[txtype].zri_print(zilog, txtype, lr);
271168404Spjd
272168404Spjd	zil_rec_info[txtype].zri_count++;
273168404Spjd	zil_rec_info[0].zri_count++;
274168404Spjd}
275168404Spjd
276168404Spjd/* ARGSUSED */
277168404Spjdstatic void
278168404Spjdprint_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t claim_txg)
279168404Spjd{
280168404Spjd	char blkbuf[BP_SPRINTF_LEN];
281168404Spjd	int verbose = MAX(dump_opt['d'], dump_opt['i']);
282168404Spjd	char *claim;
283168404Spjd
284168404Spjd	if (verbose <= 3)
285168404Spjd		return;
286168404Spjd
287168404Spjd	if (verbose >= 5) {
288168404Spjd		(void) strcpy(blkbuf, ", ");
289168404Spjd		sprintf_blkptr(blkbuf + strlen(blkbuf),
290168404Spjd		    BP_SPRINTF_LEN - strlen(blkbuf), bp);
291168404Spjd	} else {
292168404Spjd		blkbuf[0] = '\0';
293168404Spjd	}
294168404Spjd
295168404Spjd	if (claim_txg != 0)
296168404Spjd		claim = "already claimed";
297168404Spjd	else if (bp->blk_birth >= spa_first_txg(zilog->zl_spa))
298168404Spjd		claim = "will claim";
299168404Spjd	else
300168404Spjd		claim = "won't claim";
301168404Spjd
302168404Spjd	(void) printf("\tBlock seqno %llu, %s%s\n",
303168404Spjd	    (u_longlong_t)bp->blk_cksum.zc_word[ZIL_ZC_SEQ], claim, blkbuf);
304168404Spjd}
305168404Spjd
306168404Spjdstatic void
307168404Spjdprint_log_stats(int verbose)
308168404Spjd{
309168404Spjd	int i, w, p10;
310168404Spjd
311168404Spjd	if (verbose > 3)
312168404Spjd		(void) printf("\n");
313168404Spjd
314168404Spjd	if (zil_rec_info[0].zri_count == 0)
315168404Spjd		return;
316168404Spjd
317168404Spjd	for (w = 1, p10 = 10; zil_rec_info[0].zri_count >= p10; p10 *= 10)
318168404Spjd		w++;
319168404Spjd
320168404Spjd	for (i = 0; i < TX_MAX_TYPE; i++)
321168404Spjd		if (zil_rec_info[i].zri_count || verbose >= 3)
322168404Spjd			(void) printf("\t\t%s %*llu\n",
323168404Spjd			    zil_rec_info[i].zri_name, w,
324168404Spjd			    (u_longlong_t)zil_rec_info[i].zri_count);
325168404Spjd	(void) printf("\n");
326168404Spjd}
327168404Spjd
328168404Spjd/* ARGSUSED */
329168404Spjdvoid
330168404Spjddump_intent_log(zilog_t *zilog)
331168404Spjd{
332168404Spjd	const zil_header_t *zh = zilog->zl_header;
333168404Spjd	int verbose = MAX(dump_opt['d'], dump_opt['i']);
334168404Spjd	int i;
335168404Spjd
336168404Spjd	if (zh->zh_log.blk_birth == 0 || verbose < 2)
337168404Spjd		return;
338168404Spjd
339168404Spjd	(void) printf("\n    ZIL header: claim_txg %llu, seq %llu\n",
340168404Spjd	    (u_longlong_t)zh->zh_claim_txg, (u_longlong_t)zh->zh_replay_seq);
341168404Spjd
342168404Spjd	if (verbose >= 4)
343168404Spjd		print_log_bp(&zh->zh_log, "\n\tfirst block: ");
344168404Spjd
345168404Spjd	for (i = 0; i < TX_MAX_TYPE; i++)
346168404Spjd		zil_rec_info[i].zri_count = 0;
347168404Spjd
348168404Spjd	if (verbose >= 2) {
349168404Spjd		(void) printf("\n");
350168404Spjd		(void) zil_parse(zilog, print_log_block, print_log_record, NULL,
351168404Spjd		    zh->zh_claim_txg);
352168404Spjd		print_log_stats(verbose);
353168404Spjd	}
354168404Spjd}
355