xref: /dflybsd-src/sbin/hammer2/cmd_debug.c (revision 167a410d9720e60c8a92f4c69bb9a87d37572402)
19ab15106SMatthew Dillon /*
29ab15106SMatthew Dillon  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
39ab15106SMatthew Dillon  *
49ab15106SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
59ab15106SMatthew Dillon  * by Matthew Dillon <dillon@dragonflybsd.org>
69ab15106SMatthew Dillon  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
79ab15106SMatthew Dillon  *
89ab15106SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
99ab15106SMatthew Dillon  * modification, are permitted provided that the following conditions
109ab15106SMatthew Dillon  * are met:
119ab15106SMatthew Dillon  *
129ab15106SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
139ab15106SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
149ab15106SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
159ab15106SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
169ab15106SMatthew Dillon  *    the documentation and/or other materials provided with the
179ab15106SMatthew Dillon  *    distribution.
189ab15106SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
199ab15106SMatthew Dillon  *    contributors may be used to endorse or promote products derived
209ab15106SMatthew Dillon  *    from this software without specific, prior written permission.
219ab15106SMatthew Dillon  *
229ab15106SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
239ab15106SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
249ab15106SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
259ab15106SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
269ab15106SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
279ab15106SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
289ab15106SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
299ab15106SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
309ab15106SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
319ab15106SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
329ab15106SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
339ab15106SMatthew Dillon  * SUCH DAMAGE.
349ab15106SMatthew Dillon  */
359ab15106SMatthew Dillon 
369ab15106SMatthew Dillon #include "hammer2.h"
379ab15106SMatthew Dillon 
38bc8f6505STomohiro Kusumi #include <openssl/sha.h>
39bc8f6505STomohiro Kusumi 
40aa2131f0SMatthew Dillon #define GIG	(1024LL*1024*1024)
41aa2131f0SMatthew Dillon 
42d490438fSTomohiro Kusumi static int show_all_volume_headers = 0;
438ca87c4cSTomohiro Kusumi static int show_tab = 2;
4491e93d9fSTomohiro Kusumi static int show_depth = -1;
4571782ce3STomohiro Kusumi static hammer2_tid_t show_min_mirror_tid = 0;
4671782ce3STomohiro Kusumi static hammer2_tid_t show_min_modify_tid = 0;
47bd878fc9SMatthew Dillon 
481b8eded1SMatthew Dillon static void shell_msghandler(dmsg_msg_t *msg, int unmanaged);
490c3a8cd0SMatthew Dillon static void shell_ttymsg(dmsg_iocom_t *iocom);
506c129444STomohiro Kusumi static void count_blocks(hammer2_bmap_data_t *bmap, int value,
515c37bf12SMatthew Dillon 		hammer2_off_t *accum16, hammer2_off_t *accum64);
52bd878fc9SMatthew Dillon 
53bd878fc9SMatthew Dillon /************************************************************************
54bd878fc9SMatthew Dillon  *				    SHELL				*
55bd878fc9SMatthew Dillon  ************************************************************************/
569ab15106SMatthew Dillon 
579ab15106SMatthew Dillon int
cmd_shell(const char * hostname)58bd878fc9SMatthew Dillon cmd_shell(const char *hostname)
599ab15106SMatthew Dillon {
601b8eded1SMatthew Dillon 	dmsg_master_service_info_t *info;
611b8eded1SMatthew Dillon 	pthread_t thread;
621b8eded1SMatthew Dillon 	int fd;
631b8eded1SMatthew Dillon 
641b8eded1SMatthew Dillon 	fd = dmsg_connect(hostname);
651b8eded1SMatthew Dillon 	if (fd < 0)
661b8eded1SMatthew Dillon 		return 1;
671b8eded1SMatthew Dillon 
681b8eded1SMatthew Dillon 	info = malloc(sizeof(*info));
691b8eded1SMatthew Dillon 	bzero(info, sizeof(*info));
701b8eded1SMatthew Dillon 	info->fd = fd;
711b8eded1SMatthew Dillon 	info->detachme = 0;
721b8eded1SMatthew Dillon 	info->usrmsg_callback = shell_msghandler;
731b8eded1SMatthew Dillon 	info->altmsg_callback = shell_ttymsg;
741b8eded1SMatthew Dillon 	info->label = strdup("debug");
751b8eded1SMatthew Dillon 	pthread_create(&thread, NULL, dmsg_master_service, info);
761b8eded1SMatthew Dillon 	pthread_join(thread, NULL);
771b8eded1SMatthew Dillon 
781b8eded1SMatthew Dillon 	return 0;
791b8eded1SMatthew Dillon }
801b8eded1SMatthew Dillon 
811b8eded1SMatthew Dillon #if 0
821b8eded1SMatthew Dillon int
831b8eded1SMatthew Dillon cmd_shell(const char *hostname)
841b8eded1SMatthew Dillon {
850c3a8cd0SMatthew Dillon 	struct dmsg_iocom iocom;
860c3a8cd0SMatthew Dillon 	dmsg_msg_t *msg;
879ab15106SMatthew Dillon 	int fd;
889ab15106SMatthew Dillon 
899ab15106SMatthew Dillon 	/*
909ab15106SMatthew Dillon 	 * Connect to the target
919ab15106SMatthew Dillon 	 */
920c3a8cd0SMatthew Dillon 	fd = dmsg_connect(hostname);
9302454b3eSMatthew Dillon 	if (fd < 0)
9462efe6ecSMatthew Dillon 		return 1;
959ab15106SMatthew Dillon 
969ab15106SMatthew Dillon 	/*
971b8eded1SMatthew Dillon 	 * Initialize the session and transmit an empty DMSG_DBG_SHELL
981b8eded1SMatthew Dillon 	 * to cause the remote end to generate a prompt.
999ab15106SMatthew Dillon 	 */
10011f7caf4SMatthew Dillon 	dmsg_iocom_init(&iocom, fd, 0,
10111f7caf4SMatthew Dillon 			NULL,
10211f7caf4SMatthew Dillon 			shell_rcvmsg,
10311f7caf4SMatthew Dillon 			hammer2_shell_parse,
10411f7caf4SMatthew Dillon 			shell_ttymsg);
10502454b3eSMatthew Dillon 	fcntl(0, F_SETFL, O_NONBLOCK);
1069ab15106SMatthew Dillon 	printf("debug: connected\n");
1079ab15106SMatthew Dillon 
1081b8eded1SMatthew Dillon 	msg = dmsg_msg_alloc(&iocom.state0, 0, DMSG_DBG_SHELL, NULL, NULL);
1090c3a8cd0SMatthew Dillon 	dmsg_msg_write(msg);
1100c3a8cd0SMatthew Dillon 	dmsg_iocom_core(&iocom);
1119ab15106SMatthew Dillon 	fprintf(stderr, "debug: disconnected\n");
1129ab15106SMatthew Dillon 	close(fd);
1139ab15106SMatthew Dillon 	return 0;
1149ab15106SMatthew Dillon }
1151b8eded1SMatthew Dillon #endif
1169ab15106SMatthew Dillon 
1179ab15106SMatthew Dillon /*
1181b8eded1SMatthew Dillon  * Debug session front-end
1191b8eded1SMatthew Dillon  *
1200c3a8cd0SMatthew Dillon  * Callback from dmsg_iocom_core() when messages might be present
1219ab15106SMatthew Dillon  * on the socket.
1229ab15106SMatthew Dillon  */
1239ab15106SMatthew Dillon static
1249ab15106SMatthew Dillon void
shell_msghandler(dmsg_msg_t * msg,int unmanaged)1251b8eded1SMatthew Dillon shell_msghandler(dmsg_msg_t *msg, int unmanaged)
1269ab15106SMatthew Dillon {
1271b8eded1SMatthew Dillon 	dmsg_msg_t *nmsg;
1281b8eded1SMatthew Dillon 
129063639baSMatthew Dillon 	switch(msg->tcmd) {
1301b8eded1SMatthew Dillon #if 0
1315bc5bca2SMatthew Dillon 	case DMSG_LNK_ERROR:
1325bc5bca2SMatthew Dillon 	case DMSG_LNK_ERROR | DMSGF_REPLY:
13381666e1bSMatthew Dillon 		/*
13481666e1bSMatthew Dillon 		 * One-way non-transactional LNK_ERROR messages typically
13581666e1bSMatthew Dillon 		 * indicate a connection failure.  Error code 0 is used by
13681666e1bSMatthew Dillon 		 * the debug shell to indicate no more results from last cmd.
13781666e1bSMatthew Dillon 		 */
13878476205SMatthew Dillon 		if (msg->any.head.error) {
13981666e1bSMatthew Dillon 			fprintf(stderr, "Stream failure: %s\n",
1400c3a8cd0SMatthew Dillon 				dmsg_msg_str(msg));
14178476205SMatthew Dillon 		} else {
14278476205SMatthew Dillon 			write(1, "debug> ", 7);
14378476205SMatthew Dillon 		}
1449ab15106SMatthew Dillon 		break;
1455bc5bca2SMatthew Dillon 	case DMSG_LNK_ERROR | DMSGF_DELETE:
14681666e1bSMatthew Dillon 		/* ignore termination of LNK_CONN */
14781666e1bSMatthew Dillon 		break;
1481b8eded1SMatthew Dillon #endif
1495bc5bca2SMatthew Dillon 	case DMSG_DBG_SHELL:
1509ab15106SMatthew Dillon 		/*
1519ab15106SMatthew Dillon 		 * We send the commands, not accept them.
15281666e1bSMatthew Dillon 		 * (one-way message, not transactional)
1539ab15106SMatthew Dillon 		 */
1541b8eded1SMatthew Dillon 		if (unmanaged)
1550c3a8cd0SMatthew Dillon 			dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
1569ab15106SMatthew Dillon 		break;
1575bc5bca2SMatthew Dillon 	case DMSG_DBG_SHELL | DMSGF_REPLY:
1589ab15106SMatthew Dillon 		/*
1599ab15106SMatthew Dillon 		 * A reply from the remote is data we copy to stdout.
16081666e1bSMatthew Dillon 		 * (one-way message, not transactional)
1619ab15106SMatthew Dillon 		 */
1629ab15106SMatthew Dillon 		if (msg->aux_size) {
1639ab15106SMatthew Dillon 			msg->aux_data[msg->aux_size - 1] = 0;
1649ab15106SMatthew Dillon 			write(1, msg->aux_data, strlen(msg->aux_data));
1659ab15106SMatthew Dillon 		}
1669ab15106SMatthew Dillon 		break;
1671b8eded1SMatthew Dillon #if 1
1685bc5bca2SMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_CREATE:
1691b8eded1SMatthew Dillon 		fprintf(stderr, "Debug Shell received LNK_CONN\n");
1701b8eded1SMatthew Dillon 		nmsg = dmsg_msg_alloc(&msg->state->iocom->state0, 0,
1711b8eded1SMatthew Dillon 				      DMSG_DBG_SHELL,
1721b8eded1SMatthew Dillon 				      NULL, NULL);
1731b8eded1SMatthew Dillon 		dmsg_msg_write(nmsg);
1740c3a8cd0SMatthew Dillon 		dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
17581666e1bSMatthew Dillon 		break;
1765bc5bca2SMatthew Dillon 	case DMSG_LNK_CONN | DMSGF_DELETE:
17781666e1bSMatthew Dillon 		break;
1781b8eded1SMatthew Dillon #endif
1799ab15106SMatthew Dillon 	default:
18081666e1bSMatthew Dillon 		/*
18181666e1bSMatthew Dillon 		 * Ignore any unknown messages, Terminate any unknown
18281666e1bSMatthew Dillon 		 * transactions with an error.
18381666e1bSMatthew Dillon 		 */
1840c3a8cd0SMatthew Dillon 		fprintf(stderr, "Unknown message: %s\n", dmsg_msg_str(msg));
1851b8eded1SMatthew Dillon 		if (unmanaged) {
1865bc5bca2SMatthew Dillon 			if (msg->any.head.cmd & DMSGF_CREATE)
1870c3a8cd0SMatthew Dillon 				dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
1885bc5bca2SMatthew Dillon 			if (msg->any.head.cmd & DMSGF_DELETE)
1890c3a8cd0SMatthew Dillon 				dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
1901b8eded1SMatthew Dillon 		}
1919ab15106SMatthew Dillon 		break;
1929ab15106SMatthew Dillon 	}
1939ab15106SMatthew Dillon }
1949ab15106SMatthew Dillon 
1951b8eded1SMatthew Dillon /*
1961b8eded1SMatthew Dillon  * Debug session front-end
1971b8eded1SMatthew Dillon  */
1989ab15106SMatthew Dillon static
1999ab15106SMatthew Dillon void
shell_ttymsg(dmsg_iocom_t * iocom)2000c3a8cd0SMatthew Dillon shell_ttymsg(dmsg_iocom_t *iocom)
2019ab15106SMatthew Dillon {
2021b8eded1SMatthew Dillon 	dmsg_state_t *pstate;
2030c3a8cd0SMatthew Dillon 	dmsg_msg_t *msg;
2049ab15106SMatthew Dillon 	char buf[256];
2051b8eded1SMatthew Dillon 	char *cmd;
2069ab15106SMatthew Dillon 	size_t len;
2079ab15106SMatthew Dillon 
2089ab15106SMatthew Dillon 	if (fgets(buf, sizeof(buf), stdin) != NULL) {
2091b8eded1SMatthew Dillon 		if (buf[0] == '@') {
2101b8eded1SMatthew Dillon 			pstate = dmsg_findspan(strtok(buf + 1, " \t\n"));
2111b8eded1SMatthew Dillon 			cmd = strtok(NULL, "\n");
2121b8eded1SMatthew Dillon 		} else {
2131b8eded1SMatthew Dillon 			pstate = &iocom->state0;
2141b8eded1SMatthew Dillon 			cmd = strtok(buf, "\n");
2151b8eded1SMatthew Dillon 		}
2161b8eded1SMatthew Dillon 		if (cmd && pstate) {
2171b8eded1SMatthew Dillon 			len = strlen(cmd) + 1;
2181b8eded1SMatthew Dillon 			msg = dmsg_msg_alloc(pstate, len, DMSG_DBG_SHELL,
21929ead430SMatthew Dillon 					     NULL, NULL);
2201b8eded1SMatthew Dillon 			bcopy(cmd, msg->aux_data, len);
2210c3a8cd0SMatthew Dillon 			dmsg_msg_write(msg);
2221b8eded1SMatthew Dillon 		} else if (cmd) {
2231b8eded1SMatthew Dillon 			fprintf(stderr, "@msgid not found\n");
2241b8eded1SMatthew Dillon 		} else {
2251b8eded1SMatthew Dillon 			/*
2261b8eded1SMatthew Dillon 			 * This should cause the remote end to generate
2271b8eded1SMatthew Dillon 			 * a debug> prompt (and thus shows that there is
2281b8eded1SMatthew Dillon 			 * connectivity).
2291b8eded1SMatthew Dillon 			 */
2301b8eded1SMatthew Dillon 			msg = dmsg_msg_alloc(pstate, 0, DMSG_DBG_SHELL,
2311b8eded1SMatthew Dillon 					     NULL, NULL);
2321b8eded1SMatthew Dillon 			dmsg_msg_write(msg);
2331b8eded1SMatthew Dillon 		}
23402454b3eSMatthew Dillon 	} else if (feof(stdin)) {
2359ab15106SMatthew Dillon 		/*
2369ab15106SMatthew Dillon 		 * Set EOF flag without setting any error code for normal
2379ab15106SMatthew Dillon 		 * EOF.
2389ab15106SMatthew Dillon 		 */
2390c3a8cd0SMatthew Dillon 		iocom->flags |= DMSG_IOCOMF_EOF;
24002454b3eSMatthew Dillon 	} else {
24102454b3eSMatthew Dillon 		clearerr(stdin);
2429ab15106SMatthew Dillon 	}
2439ab15106SMatthew Dillon }
2449ab15106SMatthew Dillon 
2451b8eded1SMatthew Dillon /*
2461b8eded1SMatthew Dillon  * Debug session back-end (on remote side)
2471b8eded1SMatthew Dillon  */
2481b8eded1SMatthew Dillon static void shell_span(dmsg_msg_t *msg, char *cmdbuf);
2495ab1caedSMatthew Dillon static void shell_ping(dmsg_msg_t *msg, char *cmdbuf);
25081666e1bSMatthew Dillon 
25111f7caf4SMatthew Dillon void
hammer2_shell_parse(dmsg_msg_t * msg,int unmanaged)252b53e7c4fSMatthew Dillon hammer2_shell_parse(dmsg_msg_t *msg, int unmanaged)
2539ab15106SMatthew Dillon {
2541b8eded1SMatthew Dillon 	dmsg_iocom_t *iocom = msg->state->iocom;
255b53e7c4fSMatthew Dillon 	char *cmdbuf;
256b53e7c4fSMatthew Dillon 	char *cmdp;
257b53e7c4fSMatthew Dillon 	uint32_t cmd;
2589ab15106SMatthew Dillon 
259b53e7c4fSMatthew Dillon 	/*
2605ab1caedSMatthew Dillon 	 * Filter on debug shell commands and ping responses only
261b53e7c4fSMatthew Dillon 	 */
262b53e7c4fSMatthew Dillon 	cmd = msg->any.head.cmd;
2635ab1caedSMatthew Dillon 	if ((cmd & DMSGF_CMDSWMASK) == (DMSG_LNK_PING | DMSGF_REPLY)) {
2645ab1caedSMatthew Dillon 		dmsg_printf(iocom, "ping reply\n");
2655ab1caedSMatthew Dillon 		return;
2665ab1caedSMatthew Dillon 	}
2675ab1caedSMatthew Dillon 
268b53e7c4fSMatthew Dillon 	if ((cmd & DMSGF_PROTOS) != DMSG_PROTO_DBG) {
269b53e7c4fSMatthew Dillon 		if (unmanaged)
270b53e7c4fSMatthew Dillon 			dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
271b53e7c4fSMatthew Dillon 		return;
272b53e7c4fSMatthew Dillon 	}
273b53e7c4fSMatthew Dillon 	if ((cmd & DMSGF_CMDSWMASK) != DMSG_DBG_SHELL) {
274b53e7c4fSMatthew Dillon 		if (unmanaged)
275b53e7c4fSMatthew Dillon 			dmsg_msg_reply(msg, DMSG_ERR_NOSUPP);
276b53e7c4fSMatthew Dillon 		return;
277b53e7c4fSMatthew Dillon 	}
278b53e7c4fSMatthew Dillon 
279b53e7c4fSMatthew Dillon 	/*
280b53e7c4fSMatthew Dillon 	 * Debug shell command
281b53e7c4fSMatthew Dillon 	 */
282b53e7c4fSMatthew Dillon 	cmdbuf = msg->aux_data;
283b53e7c4fSMatthew Dillon 	cmdp = strsep(&cmdbuf, " \t");
284b53e7c4fSMatthew Dillon 
285b53e7c4fSMatthew Dillon 	if (cmdp == NULL || *cmdp == 0) {
2869ab15106SMatthew Dillon 		;
2875ab1caedSMatthew Dillon 	} else if (strcmp(cmdp, "ping") == 0) {
2885ab1caedSMatthew Dillon 		shell_ping(msg, cmdbuf);
289b53e7c4fSMatthew Dillon 	} else if (strcmp(cmdp, "span") == 0) {
2901b8eded1SMatthew Dillon 		shell_span(msg, cmdbuf);
291b53e7c4fSMatthew Dillon 	} else if (strcmp(cmdp, "tree") == 0) {
2921b8eded1SMatthew Dillon 		dmsg_shell_tree(iocom, cmdbuf); /* dump spanning tree */
293b53e7c4fSMatthew Dillon 	} else if (strcmp(cmdp, "help") == 0 || strcmp(cmdp, "?") == 0) {
2941b8eded1SMatthew Dillon 		dmsg_printf(iocom, "help            Command help\n");
2951b8eded1SMatthew Dillon 		dmsg_printf(iocom, "span <host>     Span to target host\n");
2961b8eded1SMatthew Dillon 		dmsg_printf(iocom, "tree            Dump spanning tree\n");
2971b8eded1SMatthew Dillon 		dmsg_printf(iocom, "@span <cmd>     Issue via circuit\n");
29881666e1bSMatthew Dillon 	} else {
2991b8eded1SMatthew Dillon 		dmsg_printf(iocom, "Unrecognized command: %s\n", cmdp);
30081666e1bSMatthew Dillon 	}
3011b8eded1SMatthew Dillon 	dmsg_printf(iocom, "debug> ");
30281666e1bSMatthew Dillon }
30381666e1bSMatthew Dillon 
30481666e1bSMatthew Dillon static void
shell_ping(dmsg_msg_t * msg,char * cmdbuf __unused)3055ab1caedSMatthew Dillon shell_ping(dmsg_msg_t *msg, char *cmdbuf __unused)
3065ab1caedSMatthew Dillon {
3075ab1caedSMatthew Dillon 	dmsg_iocom_t *iocom = msg->state->iocom;
3085ab1caedSMatthew Dillon 	dmsg_msg_t *m2;
3095ab1caedSMatthew Dillon 
3105ab1caedSMatthew Dillon 	dmsg_printf(iocom, "sending ping\n");
3115ab1caedSMatthew Dillon 	m2 = dmsg_msg_alloc(msg->state, 0, DMSG_LNK_PING, NULL, NULL);
3125ab1caedSMatthew Dillon 	dmsg_msg_write(m2);
3135ab1caedSMatthew Dillon }
3145ab1caedSMatthew Dillon 
3155ab1caedSMatthew Dillon static void
shell_span(dmsg_msg_t * msg,char * cmdbuf)3161b8eded1SMatthew Dillon shell_span(dmsg_msg_t *msg, char *cmdbuf)
31781666e1bSMatthew Dillon {
3181b8eded1SMatthew Dillon 	dmsg_iocom_t *iocom = msg->state->iocom;
319ddfbb283SMatthew Dillon 	dmsg_master_service_info_t *info;
32002454b3eSMatthew Dillon 	const char *hostname = strsep(&cmdbuf, " \t");
32102454b3eSMatthew Dillon 	pthread_t thread;
32202454b3eSMatthew Dillon 	int fd;
32302454b3eSMatthew Dillon 
32402454b3eSMatthew Dillon 	/*
32502454b3eSMatthew Dillon 	 * Connect to the target
32602454b3eSMatthew Dillon 	 */
32702454b3eSMatthew Dillon 	if (hostname == NULL) {
32802454b3eSMatthew Dillon 		fd = -1;
32902454b3eSMatthew Dillon 	} else {
3300c3a8cd0SMatthew Dillon 		fd = dmsg_connect(hostname);
33102454b3eSMatthew Dillon 	}
33202454b3eSMatthew Dillon 
33302454b3eSMatthew Dillon 	/*
33402454b3eSMatthew Dillon 	 * Start master service
33502454b3eSMatthew Dillon 	 */
33602454b3eSMatthew Dillon 	if (fd < 0) {
3371b8eded1SMatthew Dillon 		dmsg_printf(iocom, "Connection to %s failed\n", hostname);
33802454b3eSMatthew Dillon 	} else {
3391b8eded1SMatthew Dillon 		dmsg_printf(iocom, "Connected to %s\n", hostname);
340ddfbb283SMatthew Dillon 
341ddfbb283SMatthew Dillon 		info = malloc(sizeof(*info));
342ddfbb283SMatthew Dillon 		bzero(info, sizeof(*info));
343ddfbb283SMatthew Dillon 		info->fd = fd;
344ddfbb283SMatthew Dillon 		info->detachme = 1;
345b53e7c4fSMatthew Dillon 		info->usrmsg_callback = hammer2_shell_parse;
346c3711753SMatthew Dillon 		info->label = strdup("client");
347ddfbb283SMatthew Dillon 
348ddfbb283SMatthew Dillon 		pthread_create(&thread, NULL, dmsg_master_service, info);
34902454b3eSMatthew Dillon 		/*pthread_join(thread, &res);*/
35002454b3eSMatthew Dillon 	}
3519ab15106SMatthew Dillon }
3529ab15106SMatthew Dillon 
353bd878fc9SMatthew Dillon /************************************************************************
35402454b3eSMatthew Dillon  *				DEBUGSPAN				*
35502454b3eSMatthew Dillon  ************************************************************************
35602454b3eSMatthew Dillon  *
35702454b3eSMatthew Dillon  * Connect to the target manually (not via the cluster list embedded in
35802454b3eSMatthew Dillon  * a hammer2 filesystem) and initiate the SPAN protocol.
35902454b3eSMatthew Dillon  */
36002454b3eSMatthew Dillon int
cmd_debugspan(const char * hostname)36102454b3eSMatthew Dillon cmd_debugspan(const char *hostname)
36202454b3eSMatthew Dillon {
36302454b3eSMatthew Dillon 	pthread_t thread;
36402454b3eSMatthew Dillon 	int fd;
36502454b3eSMatthew Dillon 	void *res;
36602454b3eSMatthew Dillon 
36702454b3eSMatthew Dillon 	/*
36802454b3eSMatthew Dillon 	 * Connect to the target
36902454b3eSMatthew Dillon 	 */
3700c3a8cd0SMatthew Dillon 	fd = dmsg_connect(hostname);
37102454b3eSMatthew Dillon 	if (fd < 0)
37202454b3eSMatthew Dillon 		return 1;
37302454b3eSMatthew Dillon 
37402454b3eSMatthew Dillon 	printf("debugspan: connected to %s, starting CONN/SPAN\n", hostname);
3750c3a8cd0SMatthew Dillon 	pthread_create(&thread, NULL,
3760c3a8cd0SMatthew Dillon 		       dmsg_master_service, (void *)(intptr_t)fd);
37702454b3eSMatthew Dillon 	pthread_join(thread, &res);
37802454b3eSMatthew Dillon 	return(0);
37902454b3eSMatthew Dillon }
38002454b3eSMatthew Dillon 
38102454b3eSMatthew Dillon /************************************************************************
382bd878fc9SMatthew Dillon  *				    SHOW				*
383bd878fc9SMatthew Dillon  ************************************************************************/
384bd878fc9SMatthew Dillon 
3850b738157STomohiro Kusumi static void show_volhdr(hammer2_volume_data_t *voldata, int bi);
3860b738157STomohiro Kusumi static void show_bref(hammer2_volume_data_t *voldata, int tab,
387dc709019STomohiro Kusumi 			int bi, hammer2_blockref_t *bref, int norecurse);
388bd878fc9SMatthew Dillon static void tabprintf(int tab, const char *ctl, ...);
389bd878fc9SMatthew Dillon 
390ce550745STomohiro Kusumi static hammer2_off_t TotalAccum16[4]; /* includes TotalAccum64 */
391ce550745STomohiro Kusumi static hammer2_off_t TotalAccum64[4];
392ce550745STomohiro Kusumi static hammer2_off_t TotalUnavail;
393ce550745STomohiro Kusumi static hammer2_off_t TotalFreemap;
3945c37bf12SMatthew Dillon 
3950b738157STomohiro Kusumi static
3960b738157STomohiro Kusumi hammer2_off_t
get_next_volume(hammer2_volume_data_t * voldata,hammer2_off_t volu_loff)3970b738157STomohiro Kusumi get_next_volume(hammer2_volume_data_t *voldata, hammer2_off_t volu_loff)
3980b738157STomohiro Kusumi {
3990b738157STomohiro Kusumi 	hammer2_off_t ret = -1;
4000b738157STomohiro Kusumi 	int i;
4010b738157STomohiro Kusumi 
4020b738157STomohiro Kusumi 	for (i = 0; i < HAMMER2_MAX_VOLUMES; ++i) {
4030b738157STomohiro Kusumi 		hammer2_off_t tmp = voldata->volu_loff[i];
4040b738157STomohiro Kusumi 		if (tmp > volu_loff) {
4050b738157STomohiro Kusumi 			ret = tmp;
4060b738157STomohiro Kusumi 			break;
4070b738157STomohiro Kusumi 		}
4080b738157STomohiro Kusumi 	}
4090b738157STomohiro Kusumi 	return ret;
4100b738157STomohiro Kusumi }
4110b738157STomohiro Kusumi 
412bd878fc9SMatthew Dillon int
cmd_show(const char * devpath,int which)413aa2131f0SMatthew Dillon cmd_show(const char *devpath, int which)
414bd878fc9SMatthew Dillon {
415bd878fc9SMatthew Dillon 	hammer2_blockref_t broot;
416351eb452SMatthew Dillon 	hammer2_media_data_t media;
4170b738157STomohiro Kusumi 	hammer2_off_t off, volu_loff, next_volu_loff = 0;
418*167a410dSTomohiro Kusumi 	hammer2_tid_t best_mirror_tid = 0;
419*167a410dSTomohiro Kusumi 	int bests[HAMMER2_MAX_VOLUMES];
420bd878fc9SMatthew Dillon 	int fd;
421*167a410dSTomohiro Kusumi 	int i, j;
4228ca87c4cSTomohiro Kusumi 	char *env;
423bd878fc9SMatthew Dillon 
424*167a410dSTomohiro Kusumi 	memset(bests, 0xff, sizeof(bests));
425ce550745STomohiro Kusumi 	memset(TotalAccum16, 0, sizeof(TotalAccum16));
426ce550745STomohiro Kusumi 	memset(TotalAccum64, 0, sizeof(TotalAccum64));
427ea226b59STomohiro Kusumi 	TotalUnavail = TotalFreemap = 0;
4288ca87c4cSTomohiro Kusumi 
429d490438fSTomohiro Kusumi 	env = getenv("HAMMER2_SHOW_ALL_VOLUME_HEADERS");
430d490438fSTomohiro Kusumi 	if (env != NULL) {
431d490438fSTomohiro Kusumi 		show_all_volume_headers = (int)strtol(env, NULL, 0);
432d490438fSTomohiro Kusumi 		if (errno)
433d490438fSTomohiro Kusumi 			show_all_volume_headers = 0;
434b87d88f0STomohiro Kusumi 		errno = 0;
435d490438fSTomohiro Kusumi 	}
4368ca87c4cSTomohiro Kusumi 	env = getenv("HAMMER2_SHOW_TAB");
4378ca87c4cSTomohiro Kusumi 	if (env != NULL) {
4388ca87c4cSTomohiro Kusumi 		show_tab = (int)strtol(env, NULL, 0);
4398ca87c4cSTomohiro Kusumi 		if (errno || show_tab < 0 || show_tab > 8)
4408ca87c4cSTomohiro Kusumi 			show_tab = 2;
441b87d88f0STomohiro Kusumi 		errno = 0;
4428ca87c4cSTomohiro Kusumi 	}
44391e93d9fSTomohiro Kusumi 	env = getenv("HAMMER2_SHOW_DEPTH");
44491e93d9fSTomohiro Kusumi 	if (env != NULL) {
44591e93d9fSTomohiro Kusumi 		show_depth = (int)strtol(env, NULL, 0);
44691e93d9fSTomohiro Kusumi 		if (errno || show_depth < 0)
44791e93d9fSTomohiro Kusumi 			show_depth = -1;
448b87d88f0STomohiro Kusumi 		errno = 0;
44991e93d9fSTomohiro Kusumi 	}
45071782ce3STomohiro Kusumi 	env = getenv("HAMMER2_SHOW_MIN_MIRROR_TID");
45171782ce3STomohiro Kusumi 	if (env != NULL) {
45271782ce3STomohiro Kusumi 		show_min_mirror_tid = (hammer2_tid_t)strtoull(env, NULL, 16);
45371782ce3STomohiro Kusumi 		if (errno)
45471782ce3STomohiro Kusumi 			show_min_mirror_tid = 0;
455b87d88f0STomohiro Kusumi 		errno = 0;
45671782ce3STomohiro Kusumi 	}
45771782ce3STomohiro Kusumi 	env = getenv("HAMMER2_SHOW_MIN_MODIFY_TID");
45871782ce3STomohiro Kusumi 	if (env != NULL) {
45971782ce3STomohiro Kusumi 		show_min_modify_tid = (hammer2_tid_t)strtoull(env, NULL, 16);
46071782ce3STomohiro Kusumi 		if (errno)
46171782ce3STomohiro Kusumi 			show_min_modify_tid = 0;
462b87d88f0STomohiro Kusumi 		errno = 0;
46371782ce3STomohiro Kusumi 	}
4648ca87c4cSTomohiro Kusumi 
4650b738157STomohiro Kusumi 	hammer2_init_volumes(devpath, 1);
466d490438fSTomohiro Kusumi 	int all_volume_headers = VerboseOpt >= 3 || show_all_volume_headers;
467*167a410dSTomohiro Kusumi 
468*167a410dSTomohiro Kusumi 	/*
469*167a410dSTomohiro Kusumi 	 * Get best volume header for all volumes first.
470*167a410dSTomohiro Kusumi 	 */
471*167a410dSTomohiro Kusumi 	volu_loff = 0;
472*167a410dSTomohiro Kusumi 	for (i = 0; i < HAMMER2_MAX_VOLUMES; ++i) {
473*167a410dSTomohiro Kusumi 		for (j = 0; j < HAMMER2_NUM_VOLHDRS; ++j) {
474*167a410dSTomohiro Kusumi 			off = j * HAMMER2_ZONE_BYTES64;
475*167a410dSTomohiro Kusumi 			fd = hammer2_get_volume_fd(volu_loff);
476*167a410dSTomohiro Kusumi 			lseek(fd, off, SEEK_SET);
477*167a410dSTomohiro Kusumi 			if (read(fd, &media, HAMMER2_PBUFSIZE) ==
478*167a410dSTomohiro Kusumi 			    (ssize_t)HAMMER2_PBUFSIZE) {
479*167a410dSTomohiro Kusumi 				if (bests[i] < 0 || best_mirror_tid <
480*167a410dSTomohiro Kusumi 				    media.voldata.mirror_tid) {
481*167a410dSTomohiro Kusumi 					bests[i] = j;
482*167a410dSTomohiro Kusumi 					best_mirror_tid = media.voldata.mirror_tid;
483*167a410dSTomohiro Kusumi 				}
484*167a410dSTomohiro Kusumi 			}
485*167a410dSTomohiro Kusumi 		}
486*167a410dSTomohiro Kusumi 		volu_loff = get_next_volume(&media.voldata, volu_loff);
487*167a410dSTomohiro Kusumi 	}
488*167a410dSTomohiro Kusumi 
489351eb452SMatthew Dillon 	/*
490351eb452SMatthew Dillon 	 * Show the tree using the best volume header.
491351eb452SMatthew Dillon 	 * -vvv will show the tree for all four volume headers.
492351eb452SMatthew Dillon 	 */
493*167a410dSTomohiro Kusumi 	for (i = 0; i < HAMMER2_MAX_VOLUMES; ++i) {
494*167a410dSTomohiro Kusumi 		volu_loff = next_volu_loff;
495*167a410dSTomohiro Kusumi 		printf("%s\n", hammer2_get_volume_path(volu_loff));
496*167a410dSTomohiro Kusumi 		for (j = 0; j < HAMMER2_NUM_VOLHDRS; ++j) {
497bd878fc9SMatthew Dillon 			bzero(&broot, sizeof(broot));
498*167a410dSTomohiro Kusumi 			broot.data_off = (j * HAMMER2_ZONE_BYTES64) |
499*167a410dSTomohiro Kusumi 			    HAMMER2_PBUFRADIX;
5000b738157STomohiro Kusumi 			off = broot.data_off & ~HAMMER2_OFF_MASK_RADIX;
5010b738157STomohiro Kusumi 			fd = hammer2_get_volume_fd(volu_loff);
5020b738157STomohiro Kusumi 			lseek(fd, off, SEEK_SET);
503351eb452SMatthew Dillon 			if (read(fd, &media, HAMMER2_PBUFSIZE) ==
504351eb452SMatthew Dillon 			    (ssize_t)HAMMER2_PBUFSIZE) {
505351eb452SMatthew Dillon 				broot.mirror_tid = media.voldata.mirror_tid;
5061a0f56e1STomohiro Kusumi 				printf("Volume %d header %d: mirror_tid=%016jx\n",
507*167a410dSTomohiro Kusumi 				       media.voldata.volu_id, j,
5081a0f56e1STomohiro Kusumi 				       (intmax_t)broot.mirror_tid);
509*167a410dSTomohiro Kusumi 				if (all_volume_headers || bests[i] == j) {
510aa2131f0SMatthew Dillon 					switch(which) {
511aa2131f0SMatthew Dillon 					case 0:
512aa2131f0SMatthew Dillon 						broot.type = HAMMER2_BREF_TYPE_VOLUME;
513*167a410dSTomohiro Kusumi 						show_bref(&media.voldata, 0, j,
514*167a410dSTomohiro Kusumi 							  &broot, 0);
515*167a410dSTomohiro Kusumi 						next_volu_loff = -1;
516aa2131f0SMatthew Dillon 						break;
517aa2131f0SMatthew Dillon 					case 1:
518aa2131f0SMatthew Dillon 						broot.type = HAMMER2_BREF_TYPE_FREEMAP;
519*167a410dSTomohiro Kusumi 						show_bref(&media.voldata, 0, j,
520*167a410dSTomohiro Kusumi 							  &broot, 0);
521*167a410dSTomohiro Kusumi 						next_volu_loff = -1;
522aa2131f0SMatthew Dillon 						break;
523aa2131f0SMatthew Dillon 					default:
524*167a410dSTomohiro Kusumi 						show_volhdr(&media.voldata, j);
525*167a410dSTomohiro Kusumi 						next_volu_loff = get_next_volume(
526*167a410dSTomohiro Kusumi 						    &media.voldata, volu_loff);
527aa2131f0SMatthew Dillon 						break;
528aa2131f0SMatthew Dillon 					}
529*167a410dSTomohiro Kusumi 				if (all_volume_headers && j != HAMMER2_NUM_VOLHDRS - 1)
530aa2131f0SMatthew Dillon 					printf("\n");
5319061bde5SMatthew Dillon 				}
532351eb452SMatthew Dillon 			}
533aa2131f0SMatthew Dillon 		}
534*167a410dSTomohiro Kusumi 		if (next_volu_loff == (hammer2_off_t)-1)
535*167a410dSTomohiro Kusumi 			break;
536*167a410dSTomohiro Kusumi 		if (i != HAMMER2_MAX_VOLUMES - 1)
5370b738157STomohiro Kusumi 			printf("---------------------------------------------\n");
538aa2131f0SMatthew Dillon 	}
539bd878fc9SMatthew Dillon 
540aa2131f0SMatthew Dillon 	if (which == 1 && VerboseOpt < 3) {
5418fbce03dSTomohiro Kusumi 		printf("Total unallocated storage:   %6.3fGB (%6.3fGB in 64KB chunks)\n",
542ce550745STomohiro Kusumi 		       (double)TotalAccum16[0] / GIG,
543ce550745STomohiro Kusumi 		       (double)TotalAccum64[0] / GIG);
5448fbce03dSTomohiro Kusumi 		printf("Total possibly free storage: %6.3fGB (%6.3fGB in 64KB chunks)\n",
545ce550745STomohiro Kusumi 		       (double)TotalAccum16[2] / GIG,
546ce550745STomohiro Kusumi 		       (double)TotalAccum64[2] / GIG);
5478fbce03dSTomohiro Kusumi 		printf("Total allocated storage:     %6.3fGB (%6.3fGB in 64KB chunks)\n",
548ce550745STomohiro Kusumi 		       (double)TotalAccum16[3] / GIG,
549ce550745STomohiro Kusumi 		       (double)TotalAccum64[3] / GIG);
5508fbce03dSTomohiro Kusumi 		printf("Total unavailable storage:   %6.3fGB\n",
551ce550745STomohiro Kusumi 		       (double)TotalUnavail / GIG);
5528fbce03dSTomohiro Kusumi 		printf("Total freemap storage:       %6.3fGB\n",
553ce550745STomohiro Kusumi 		       (double)TotalFreemap / GIG);
5545c37bf12SMatthew Dillon 	}
5550b738157STomohiro Kusumi 	hammer2_cleanup_volumes();
5565c37bf12SMatthew Dillon 
557bd878fc9SMatthew Dillon 	return 0;
558bd878fc9SMatthew Dillon }
559bd878fc9SMatthew Dillon 
560bd878fc9SMatthew Dillon static void
show_volhdr(hammer2_volume_data_t * voldata,int bi)5610b738157STomohiro Kusumi show_volhdr(hammer2_volume_data_t *voldata, int bi)
562aa2131f0SMatthew Dillon {
563aa2131f0SMatthew Dillon 	uint32_t status;
564aa2131f0SMatthew Dillon 	uint32_t i;
565aa2131f0SMatthew Dillon 	char *str;
566aa2131f0SMatthew Dillon 	char *name;
5670b738157STomohiro Kusumi 	char *buf;
568bc092eefSTomohiro Kusumi 	uuid_t uuid;
569aa2131f0SMatthew Dillon 
5701a0f56e1STomohiro Kusumi 	printf("\nVolume %d header %d {\n", voldata->volu_id, bi);
571aa2131f0SMatthew Dillon 	printf("    magic          0x%016jx\n", (intmax_t)voldata->magic);
572aa2131f0SMatthew Dillon 	printf("    boot_beg       0x%016jx\n", (intmax_t)voldata->boot_beg);
573aa2131f0SMatthew Dillon 	printf("    boot_end       0x%016jx (%6.2fMB)\n",
574aa2131f0SMatthew Dillon 	       (intmax_t)voldata->boot_end,
575aa2131f0SMatthew Dillon 	       (double)(voldata->boot_end - voldata->boot_beg) /
576aa2131f0SMatthew Dillon 	       (1024.0*1024.0));
577aa2131f0SMatthew Dillon 	printf("    aux_beg        0x%016jx\n", (intmax_t)voldata->aux_beg);
578aa2131f0SMatthew Dillon 	printf("    aux_end        0x%016jx (%6.2fMB)\n",
579aa2131f0SMatthew Dillon 	       (intmax_t)voldata->aux_end,
580aa2131f0SMatthew Dillon 	       (double)(voldata->aux_end - voldata->aux_beg) /
581aa2131f0SMatthew Dillon 	       (1024.0*1024.0));
5828fbce03dSTomohiro Kusumi 	printf("    volu_size      0x%016jx (%6.2fGB)\n",
583aa2131f0SMatthew Dillon 	       (intmax_t)voldata->volu_size,
584aa2131f0SMatthew Dillon 	       (double)voldata->volu_size / GIG);
585aa2131f0SMatthew Dillon 	printf("    version        %d\n", voldata->version);
586aa2131f0SMatthew Dillon 	printf("    flags          0x%08x\n", voldata->flags);
587aa2131f0SMatthew Dillon 	printf("    copyid         %d\n", voldata->copyid);
588aa2131f0SMatthew Dillon 	printf("    freemap_vers   %d\n", voldata->freemap_version);
589aa2131f0SMatthew Dillon 	printf("    peer_type      %d\n", voldata->peer_type);
5900b738157STomohiro Kusumi 	printf("    volu_id        %d\n", voldata->volu_id);
5910b738157STomohiro Kusumi 	printf("    nvolumes       %d\n", voldata->nvolumes);
592aa2131f0SMatthew Dillon 
593aa2131f0SMatthew Dillon 	str = NULL;
594bc092eefSTomohiro Kusumi 	uuid = voldata->fsid;
595bc092eefSTomohiro Kusumi 	hammer2_uuid_to_str(&uuid, &str);
596aa2131f0SMatthew Dillon 	printf("    fsid           %s\n", str);
597aa2131f0SMatthew Dillon 	free(str);
598aa2131f0SMatthew Dillon 
599aa2131f0SMatthew Dillon 	str = NULL;
600aa2131f0SMatthew Dillon 	name = NULL;
601bc092eefSTomohiro Kusumi 	uuid = voldata->fstype;
602bc092eefSTomohiro Kusumi 	hammer2_uuid_to_str(&uuid, &str);
603aa2131f0SMatthew Dillon 	printf("    fstype         %s\n", str);
604aa2131f0SMatthew Dillon 	uuid_addr_lookup(&voldata->fstype, &name, &status);
605aa2131f0SMatthew Dillon 	if (name == NULL)
606aa2131f0SMatthew Dillon 		name = strdup("?");
607aa2131f0SMatthew Dillon 	printf("                   (%s)\n", name);
608aa2131f0SMatthew Dillon 	free(name);
609aa2131f0SMatthew Dillon 	free(str);
610aa2131f0SMatthew Dillon 
6118fbce03dSTomohiro Kusumi 	printf("    allocator_size 0x%016jx (%6.2fGB)\n",
612aa2131f0SMatthew Dillon 	       voldata->allocator_size,
613aa2131f0SMatthew Dillon 	       (double)voldata->allocator_size / GIG);
6148fbce03dSTomohiro Kusumi 	printf("    allocator_free 0x%016jx (%6.2fGB)\n",
615aa2131f0SMatthew Dillon 	       voldata->allocator_free,
616aa2131f0SMatthew Dillon 	       (double)voldata->allocator_free / GIG);
6178fbce03dSTomohiro Kusumi 	printf("    allocator_beg  0x%016jx (%6.2fGB)\n",
618aa2131f0SMatthew Dillon 	       voldata->allocator_beg,
619aa2131f0SMatthew Dillon 	       (double)voldata->allocator_beg / GIG);
620aa2131f0SMatthew Dillon 
621aa2131f0SMatthew Dillon 	printf("    mirror_tid     0x%016jx\n", voldata->mirror_tid);
622aa2131f0SMatthew Dillon 	printf("    reserved0080   0x%016jx\n", voldata->reserved0080);
623aa2131f0SMatthew Dillon 	printf("    reserved0088   0x%016jx\n", voldata->reserved0088);
624aa2131f0SMatthew Dillon 	printf("    freemap_tid    0x%016jx\n", voldata->freemap_tid);
625ed383a46STomohiro Kusumi 	printf("    bulkfree_tid   0x%016jx\n", voldata->bulkfree_tid);
6264db52a5aSTomohiro Kusumi 	for (i = 0; i < nitems(voldata->reserved00A0); ++i) {
627aa2131f0SMatthew Dillon 		printf("    reserved00A0/%u 0x%016jx\n",
628aa2131f0SMatthew Dillon 		       i, voldata->reserved00A0[0]);
629aa2131f0SMatthew Dillon 	}
6300b738157STomohiro Kusumi 	printf("    total_size     0x%016jx\n", voldata->total_size);
631aa2131f0SMatthew Dillon 
632aa2131f0SMatthew Dillon 	printf("    copyexists    ");
6334db52a5aSTomohiro Kusumi 	for (i = 0; i < nitems(voldata->copyexists); ++i)
634aa2131f0SMatthew Dillon 		printf(" 0x%02x", voldata->copyexists[i]);
635aa2131f0SMatthew Dillon 	printf("\n");
636aa2131f0SMatthew Dillon 
637aa2131f0SMatthew Dillon 	/*
638aa2131f0SMatthew Dillon 	 * NOTE: Index numbers and ICRC_SECTn definitions are not matched,
639aa2131f0SMatthew Dillon 	 *	 the ICRC for sector 0 actually uses the last index, for
640aa2131f0SMatthew Dillon 	 *	 example.
641aa2131f0SMatthew Dillon 	 *
642aa2131f0SMatthew Dillon 	 * NOTE: The whole voldata CRC does not have to match critically
643aa2131f0SMatthew Dillon 	 *	 as certain sub-areas of the volume header have their own
644aa2131f0SMatthew Dillon 	 *	 CRCs.
645aa2131f0SMatthew Dillon 	 */
646aa2131f0SMatthew Dillon 	printf("\n");
6474db52a5aSTomohiro Kusumi 	for (i = 0; i < nitems(voldata->icrc_sects); ++i) {
648aa2131f0SMatthew Dillon 		printf("    icrc_sects[%u]  ", i);
649aa2131f0SMatthew Dillon 		switch(i) {
650aa2131f0SMatthew Dillon 		case HAMMER2_VOL_ICRC_SECT0:
651aa2131f0SMatthew Dillon 			printf("0x%08x/0x%08x",
652aa2131f0SMatthew Dillon 			       hammer2_icrc32((char *)voldata +
653aa2131f0SMatthew Dillon 					      HAMMER2_VOLUME_ICRC0_OFF,
654aa2131f0SMatthew Dillon 					      HAMMER2_VOLUME_ICRC0_SIZE),
655aa2131f0SMatthew Dillon 			       voldata->icrc_sects[HAMMER2_VOL_ICRC_SECT0]);
656aa2131f0SMatthew Dillon 			if (hammer2_icrc32((char *)voldata +
657aa2131f0SMatthew Dillon 					   HAMMER2_VOLUME_ICRC0_OFF,
658aa2131f0SMatthew Dillon 					   HAMMER2_VOLUME_ICRC0_SIZE) ==
659aa2131f0SMatthew Dillon 			       voldata->icrc_sects[HAMMER2_VOL_ICRC_SECT0]) {
660aa2131f0SMatthew Dillon 				printf(" (OK)");
661aa2131f0SMatthew Dillon 			} else {
662aa2131f0SMatthew Dillon 				printf(" (FAILED)");
663aa2131f0SMatthew Dillon 			}
664aa2131f0SMatthew Dillon 			break;
665aa2131f0SMatthew Dillon 		case HAMMER2_VOL_ICRC_SECT1:
666aa2131f0SMatthew Dillon 			printf("0x%08x/0x%08x",
667aa2131f0SMatthew Dillon 			       hammer2_icrc32((char *)voldata +
668aa2131f0SMatthew Dillon 					      HAMMER2_VOLUME_ICRC1_OFF,
669aa2131f0SMatthew Dillon 					      HAMMER2_VOLUME_ICRC1_SIZE),
670aa2131f0SMatthew Dillon 			       voldata->icrc_sects[HAMMER2_VOL_ICRC_SECT1]);
671aa2131f0SMatthew Dillon 			if (hammer2_icrc32((char *)voldata +
672aa2131f0SMatthew Dillon 					   HAMMER2_VOLUME_ICRC1_OFF,
673aa2131f0SMatthew Dillon 					   HAMMER2_VOLUME_ICRC1_SIZE) ==
674aa2131f0SMatthew Dillon 			       voldata->icrc_sects[HAMMER2_VOL_ICRC_SECT1]) {
675aa2131f0SMatthew Dillon 				printf(" (OK)");
676aa2131f0SMatthew Dillon 			} else {
677aa2131f0SMatthew Dillon 				printf(" (FAILED)");
678aa2131f0SMatthew Dillon 			}
679aa2131f0SMatthew Dillon 
680aa2131f0SMatthew Dillon 			break;
681aa2131f0SMatthew Dillon 		default:
682aa2131f0SMatthew Dillon 			printf("0x%08x (reserved)", voldata->icrc_sects[i]);
683aa2131f0SMatthew Dillon 			break;
684aa2131f0SMatthew Dillon 		}
685aa2131f0SMatthew Dillon 		printf("\n");
686aa2131f0SMatthew Dillon 	}
687aa2131f0SMatthew Dillon 	printf("    icrc_volhdr    0x%08x/0x%08x",
688aa2131f0SMatthew Dillon 	       hammer2_icrc32((char *)voldata + HAMMER2_VOLUME_ICRCVH_OFF,
689aa2131f0SMatthew Dillon 			      HAMMER2_VOLUME_ICRCVH_SIZE),
690aa2131f0SMatthew Dillon 	       voldata->icrc_volheader);
691aa2131f0SMatthew Dillon 	if (hammer2_icrc32((char *)voldata + HAMMER2_VOLUME_ICRCVH_OFF,
692aa2131f0SMatthew Dillon 			   HAMMER2_VOLUME_ICRCVH_SIZE) ==
693aa2131f0SMatthew Dillon 	    voldata->icrc_volheader) {
694aa2131f0SMatthew Dillon 		printf(" (OK)\n");
695aa2131f0SMatthew Dillon 	} else {
696aa2131f0SMatthew Dillon 		printf(" (FAILED - not a critical error)\n");
697aa2131f0SMatthew Dillon 	}
698aa2131f0SMatthew Dillon 
699aa2131f0SMatthew Dillon 	/*
700aa2131f0SMatthew Dillon 	 * The super-root and freemap blocksets (not recursed)
701aa2131f0SMatthew Dillon 	 */
702aa2131f0SMatthew Dillon 	printf("\n");
703aa2131f0SMatthew Dillon 	printf("    sroot_blockset {\n");
704aa2131f0SMatthew Dillon 	for (i = 0; i < HAMMER2_SET_COUNT; ++i) {
7050b738157STomohiro Kusumi 		show_bref(voldata, 16, i,
706aa2131f0SMatthew Dillon 			  &voldata->sroot_blockset.blockref[i], 2);
707aa2131f0SMatthew Dillon 	}
708aa2131f0SMatthew Dillon 	printf("    }\n");
709aa2131f0SMatthew Dillon 
710aa2131f0SMatthew Dillon 	printf("    freemap_blockset {\n");
711aa2131f0SMatthew Dillon 	for (i = 0; i < HAMMER2_SET_COUNT; ++i) {
7120b738157STomohiro Kusumi 		show_bref(voldata, 16, i,
713aa2131f0SMatthew Dillon 			  &voldata->freemap_blockset.blockref[i], 2);
714aa2131f0SMatthew Dillon 	}
715aa2131f0SMatthew Dillon 	printf("    }\n");
716aa2131f0SMatthew Dillon 
7170b738157STomohiro Kusumi 	buf = calloc(1, sizeof(voldata->volu_loff));
7180b738157STomohiro Kusumi 	if (bcmp(buf, voldata->volu_loff, sizeof(voldata->volu_loff))) {
7190b738157STomohiro Kusumi 		printf("\n");
7200b738157STomohiro Kusumi 		for (i = 0; i < HAMMER2_MAX_VOLUMES; ++i) {
7210b738157STomohiro Kusumi 			hammer2_off_t loff = voldata->volu_loff[i];
7220b738157STomohiro Kusumi 			if (loff != (hammer2_off_t)-1)
7230b738157STomohiro Kusumi 				printf("    volu_loff[%d]   0x%016jx\n", i, loff);
7240b738157STomohiro Kusumi 		}
7250b738157STomohiro Kusumi 	}
7260b738157STomohiro Kusumi 	free(buf);
7270b738157STomohiro Kusumi 
728aa2131f0SMatthew Dillon 	printf("}\n");
729aa2131f0SMatthew Dillon }
730aa2131f0SMatthew Dillon 
731aa2131f0SMatthew Dillon static void
show_bref(hammer2_volume_data_t * voldata,int tab,int bi,hammer2_blockref_t * bref,int norecurse)7320b738157STomohiro Kusumi show_bref(hammer2_volume_data_t *voldata, int tab, int bi,
7330b738157STomohiro Kusumi 	  hammer2_blockref_t *bref, int norecurse)
734bd878fc9SMatthew Dillon {
735bd878fc9SMatthew Dillon 	hammer2_media_data_t media;
736bd878fc9SMatthew Dillon 	hammer2_blockref_t *bscan;
737906f9d76STomohiro Kusumi 	hammer2_off_t tmp;
7380b738157STomohiro Kusumi 	int i, bcount, namelen, failed, obrace, fd;
739aa2131f0SMatthew Dillon 	int type_pad;
740bd878fc9SMatthew Dillon 	size_t bytes;
741bd878fc9SMatthew Dillon 	const char *type_str;
742bd878fc9SMatthew Dillon 	char *str = NULL;
743d086b553STomohiro Kusumi 	char check_str[32], comp_str[32];
744d086b553STomohiro Kusumi 	uint8_t check_algo, comp_algo;
7455a790ddfSMatthew Dillon 	uint32_t cv;
7467d565a4fSMatthew Dillon 	uint64_t cv64;
74791e93d9fSTomohiro Kusumi 	static int init_tab = -1;
748bc092eefSTomohiro Kusumi 	uuid_t uuid;
749bd878fc9SMatthew Dillon 
750bc8f6505STomohiro Kusumi 	SHA256_CTX hash_ctx;
751bc8f6505STomohiro Kusumi 	union {
752bc8f6505STomohiro Kusumi 		uint8_t digest[SHA256_DIGEST_LENGTH];
753bc8f6505STomohiro Kusumi 		uint64_t digest64[SHA256_DIGEST_LENGTH/8];
754bc8f6505STomohiro Kusumi 	} u;
755bc8f6505STomohiro Kusumi 
75671782ce3STomohiro Kusumi 	/* omit if smaller than mininum mirror_tid threshold */
75771782ce3STomohiro Kusumi 	if (bref->mirror_tid < show_min_mirror_tid)
75871782ce3STomohiro Kusumi 		return;
75971782ce3STomohiro Kusumi 	/* omit if smaller than mininum modify_tid threshold */
76071782ce3STomohiro Kusumi 	if (bref->modify_tid < show_min_modify_tid) {
76171782ce3STomohiro Kusumi 		if (bref->modify_tid)
76271782ce3STomohiro Kusumi 			return;
76371782ce3STomohiro Kusumi 		else if (bref->type == HAMMER2_BREF_TYPE_INODE && !bref->leaf_count)
76471782ce3STomohiro Kusumi 			return;
76571782ce3STomohiro Kusumi 	}
76671782ce3STomohiro Kusumi 
76791e93d9fSTomohiro Kusumi 	if (init_tab == -1)
76891e93d9fSTomohiro Kusumi 		init_tab = tab;
76991e93d9fSTomohiro Kusumi 
770da0cdd33SMatthew Dillon 	bytes = (bref->data_off & HAMMER2_OFF_MASK_RADIX);
771da0cdd33SMatthew Dillon 	if (bytes)
772da0cdd33SMatthew Dillon 		bytes = (size_t)1 << bytes;
773da0cdd33SMatthew Dillon 	if (bytes) {
77478ac5385SMatthew Dillon 		hammer2_off_t io_off;
77578ac5385SMatthew Dillon 		hammer2_off_t io_base;
77678ac5385SMatthew Dillon 		size_t io_bytes;
77778ac5385SMatthew Dillon 		size_t boff;
77878ac5385SMatthew Dillon 
77978ac5385SMatthew Dillon 		io_off = bref->data_off & ~HAMMER2_OFF_MASK_RADIX;
7805dade8cfSTomohiro Kusumi 		io_base = io_off & ~(hammer2_off_t)(HAMMER2_LBUFSIZE - 1);
78178ac5385SMatthew Dillon 		boff = io_off - io_base;
78278ac5385SMatthew Dillon 
7835dade8cfSTomohiro Kusumi 		io_bytes = HAMMER2_LBUFSIZE;
78478ac5385SMatthew Dillon 		while (io_bytes + boff < bytes)
78578ac5385SMatthew Dillon 			io_bytes <<= 1;
78678ac5385SMatthew Dillon 
78778ac5385SMatthew Dillon 		if (io_bytes > sizeof(media)) {
7889317c2d0SSascha Wildner 			printf("(bad block size %zu)\n", bytes);
789bd878fc9SMatthew Dillon 			return;
790bd878fc9SMatthew Dillon 		}
791bd878fc9SMatthew Dillon 		if (bref->type != HAMMER2_BREF_TYPE_DATA || VerboseOpt >= 1) {
7920b738157STomohiro Kusumi 			fd = hammer2_get_volume_fd(io_off);
7930b738157STomohiro Kusumi 			lseek(fd, io_base - hammer2_get_volume_offset(io_base),
7940b738157STomohiro Kusumi 			      SEEK_SET);
79578ac5385SMatthew Dillon 			if (read(fd, &media, io_bytes) != (ssize_t)io_bytes) {
796bd878fc9SMatthew Dillon 				printf("(media read failed)\n");
797bd878fc9SMatthew Dillon 				return;
798bd878fc9SMatthew Dillon 			}
79978ac5385SMatthew Dillon 			if (boff)
80078ac5385SMatthew Dillon 				bcopy((char *)&media + boff, &media, bytes);
80178ac5385SMatthew Dillon 		}
802bd878fc9SMatthew Dillon 	}
803bd878fc9SMatthew Dillon 
804bd878fc9SMatthew Dillon 	bscan = NULL;
805bd878fc9SMatthew Dillon 	bcount = 0;
8061fca819aSMatthew Dillon 	namelen = 0;
80762a2c422SMatthew Dillon 	failed = 0;
808047d51c8STomohiro Kusumi 	obrace = 1;
809bd878fc9SMatthew Dillon 
81094a97128STomohiro Kusumi 	type_str = hammer2_breftype_to_str(bref->type);
811aa2131f0SMatthew Dillon 	type_pad = 8 - strlen(type_str);
812aa2131f0SMatthew Dillon 	if (type_pad < 0)
813aa2131f0SMatthew Dillon 		type_pad = 0;
814043b0b59STomohiro Kusumi 
815043b0b59STomohiro Kusumi 	switch(bref->type) {
816043b0b59STomohiro Kusumi 	case HAMMER2_BREF_TYPE_INODE:
817ae2f457fSTomohiro Kusumi 		assert(bytes);
818043b0b59STomohiro Kusumi 		if (!(media.ipdata.meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA)) {
819043b0b59STomohiro Kusumi 			bscan = &media.ipdata.u.blockset.blockref[0];
820043b0b59STomohiro Kusumi 			bcount = HAMMER2_SET_COUNT;
821043b0b59STomohiro Kusumi 		}
822043b0b59STomohiro Kusumi 		break;
823043b0b59STomohiro Kusumi 	case HAMMER2_BREF_TYPE_INDIRECT:
824ae2f457fSTomohiro Kusumi 		assert(bytes);
825043b0b59STomohiro Kusumi 		bscan = &media.npdata[0];
826043b0b59STomohiro Kusumi 		bcount = bytes / sizeof(hammer2_blockref_t);
827043b0b59STomohiro Kusumi 		break;
828043b0b59STomohiro Kusumi 	case HAMMER2_BREF_TYPE_VOLUME:
829043b0b59STomohiro Kusumi 		bscan = &media.voldata.sroot_blockset.blockref[0];
830043b0b59STomohiro Kusumi 		bcount = HAMMER2_SET_COUNT;
831043b0b59STomohiro Kusumi 		break;
832043b0b59STomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP:
833043b0b59STomohiro Kusumi 		bscan = &media.voldata.freemap_blockset.blockref[0];
834043b0b59STomohiro Kusumi 		bcount = HAMMER2_SET_COUNT;
835043b0b59STomohiro Kusumi 		break;
836043b0b59STomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP_NODE:
837ae2f457fSTomohiro Kusumi 		assert(bytes);
838043b0b59STomohiro Kusumi 		bscan = &media.npdata[0];
839043b0b59STomohiro Kusumi 		bcount = bytes / sizeof(hammer2_blockref_t);
840043b0b59STomohiro Kusumi 		break;
841043b0b59STomohiro Kusumi 	}
842043b0b59STomohiro Kusumi 
843e3bf7c89STomohiro Kusumi 	if (QuietOpt > 0) {
844e3bf7c89STomohiro Kusumi 		tabprintf(tab,
845e3bf7c89STomohiro Kusumi 			  "%s.%-3d %016jx %016jx/%-2d "
8460b738157STomohiro Kusumi 			  "vol=%d mir=%016jx mod=%016jx leafcnt=%d ",
847e3bf7c89STomohiro Kusumi 			  type_str, bi, (intmax_t)bref->data_off,
848e3bf7c89STomohiro Kusumi 			  (intmax_t)bref->key, (intmax_t)bref->keybits,
8490b738157STomohiro Kusumi 			  hammer2_get_volume_id(bref->data_off),
850e3bf7c89STomohiro Kusumi 			  (intmax_t)bref->mirror_tid,
851e3bf7c89STomohiro Kusumi 			  (intmax_t)bref->modify_tid,
852e3bf7c89STomohiro Kusumi 			  bref->leaf_count);
853e3bf7c89STomohiro Kusumi 	} else {
8540425627bSTomohiro Kusumi 		tabprintf(tab, "%s.%-3d%*.*s %016jx %016jx/%-2d ",
855aa2131f0SMatthew Dillon 			  type_str, bi, type_pad, type_pad, "",
856aa2131f0SMatthew Dillon 			  (intmax_t)bref->data_off,
857aa2131f0SMatthew Dillon 			  (intmax_t)bref->key, (intmax_t)bref->keybits);
858aa2131f0SMatthew Dillon 		/*if (norecurse > 1)*/ {
859aa2131f0SMatthew Dillon 			printf("\n");
860aa2131f0SMatthew Dillon 			tabprintf(tab + 13, "");
861aa2131f0SMatthew Dillon 		}
8620b738157STomohiro Kusumi 		printf("vol=%d mir=%016jx mod=%016jx lfcnt=%d ",
8630b738157STomohiro Kusumi 		       hammer2_get_volume_id(bref->data_off),
864043b0b59STomohiro Kusumi 		       (intmax_t)bref->mirror_tid, (intmax_t)bref->modify_tid,
865043b0b59STomohiro Kusumi 		       bref->leaf_count);
866aa2131f0SMatthew Dillon 		if (/*norecurse > 1 && */ (bcount || bref->flags ||
867aa2131f0SMatthew Dillon 		    bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE ||
868aa2131f0SMatthew Dillon 		    bref->type == HAMMER2_BREF_TYPE_FREEMAP_LEAF)) {
869aa2131f0SMatthew Dillon 			printf("\n");
870aa2131f0SMatthew Dillon 			tabprintf(tab + 13, "");
871aa2131f0SMatthew Dillon 		}
872e3bf7c89STomohiro Kusumi 	}
873aa2131f0SMatthew Dillon 
8744d08bfebSTomohiro Kusumi 	if (bcount)
8754d08bfebSTomohiro Kusumi 		printf("bcnt=%d ", bcount);
876043b0b59STomohiro Kusumi 	if (bref->flags)
877043b0b59STomohiro Kusumi 		printf("flags=%02x ", bref->flags);
878043b0b59STomohiro Kusumi 	if (bref->type == HAMMER2_BREF_TYPE_FREEMAP_NODE ||
879043b0b59STomohiro Kusumi 	    bref->type == HAMMER2_BREF_TYPE_FREEMAP_LEAF) {
88033b364a7STomohiro Kusumi 		printf("bigmask=%08x avail=%ju ",
88133b364a7STomohiro Kusumi 			bref->check.freemap.bigmask,
88233b364a7STomohiro Kusumi 			(uintmax_t)bref->check.freemap.avail);
883043b0b59STomohiro Kusumi 	}
884043b0b59STomohiro Kusumi 
8855a790ddfSMatthew Dillon 	/*
8865a790ddfSMatthew Dillon 	 * Check data integrity in verbose mode, otherwise we are just doing
8875a790ddfSMatthew Dillon 	 * a quick meta-data scan.  Meta-data integrity is always checked.
8885a790ddfSMatthew Dillon 	 * (Also see the check above that ensures the media data is loaded,
8895a790ddfSMatthew Dillon 	 * otherwise there's no data to check!).
890da0cdd33SMatthew Dillon 	 *
891da0cdd33SMatthew Dillon 	 * WARNING! bref->check state may be used for other things when
892da0cdd33SMatthew Dillon 	 *	    bref has no data (bytes == 0).
8935a790ddfSMatthew Dillon 	 */
894da0cdd33SMatthew Dillon 	if (bytes &&
895da0cdd33SMatthew Dillon 	    (bref->type != HAMMER2_BREF_TYPE_DATA || VerboseOpt >= 1)) {
896e3bf7c89STomohiro Kusumi 		if (!(QuietOpt > 0)) {
897aa2131f0SMatthew Dillon 			/*if (norecurse > 1)*/ {
898aa2131f0SMatthew Dillon 				printf("\n");
899aa2131f0SMatthew Dillon 				tabprintf(tab + 13, "");
900aa2131f0SMatthew Dillon 			}
901e3bf7c89STomohiro Kusumi 		}
902aa2131f0SMatthew Dillon 
903d086b553STomohiro Kusumi 		check_algo = HAMMER2_DEC_CHECK(bref->methods);
904d086b553STomohiro Kusumi 		strlcpy(check_str, hammer2_checkmode_to_str(check_algo),
905d086b553STomohiro Kusumi 			sizeof(check_str));
906d086b553STomohiro Kusumi 		comp_algo = HAMMER2_DEC_COMP(bref->methods);
907d086b553STomohiro Kusumi 		strlcpy(comp_str, hammer2_compmode_to_str(comp_algo),
908d086b553STomohiro Kusumi 			sizeof(comp_str));
909d086b553STomohiro Kusumi 
910d086b553STomohiro Kusumi 		switch(check_algo) {
9115a790ddfSMatthew Dillon 		case HAMMER2_CHECK_NONE:
912d086b553STomohiro Kusumi 			printf("meth=%s|%s ", check_str, comp_str);
9138adee7deSMatthew Dillon 			break;
9148adee7deSMatthew Dillon 		case HAMMER2_CHECK_DISABLED:
915d086b553STomohiro Kusumi 			printf("meth=%s|%s ", check_str, comp_str);
9165a790ddfSMatthew Dillon 			break;
9175a790ddfSMatthew Dillon 		case HAMMER2_CHECK_ISCSI32:
9185a790ddfSMatthew Dillon 			cv = hammer2_icrc32(&media, bytes);
9195a790ddfSMatthew Dillon 			if (bref->check.iscsi32.value != cv) {
920d086b553STomohiro Kusumi 				printf("(icrc %s|%s %08x/%08x failed) ",
921d086b553STomohiro Kusumi 				       check_str, comp_str,
9225a790ddfSMatthew Dillon 				       bref->check.iscsi32.value,
9235a790ddfSMatthew Dillon 				       cv);
92462a2c422SMatthew Dillon 				failed = 1;
9258adee7deSMatthew Dillon 			} else {
926d086b553STomohiro Kusumi 				printf("meth=%s|%s iscsi32=%08x ",
927d086b553STomohiro Kusumi 				       check_str, comp_str, cv);
9285a790ddfSMatthew Dillon 			}
9295a790ddfSMatthew Dillon 			break;
9307d565a4fSMatthew Dillon 		case HAMMER2_CHECK_XXHASH64:
9317d565a4fSMatthew Dillon 			cv64 = XXH64(&media, bytes, XXH_HAMMER2_SEED);
9327d565a4fSMatthew Dillon 			if (bref->check.xxhash64.value != cv64) {
933d086b553STomohiro Kusumi 				printf("(xxhash64 %s|%s %016jx/%016jx failed) ",
934d086b553STomohiro Kusumi 				       check_str, comp_str,
9357d565a4fSMatthew Dillon 				       bref->check.xxhash64.value,
9367d565a4fSMatthew Dillon 				       cv64);
93762a2c422SMatthew Dillon 				failed = 1;
9387d565a4fSMatthew Dillon 			} else {
939d086b553STomohiro Kusumi 				printf("meth=%s|%s xxh=%016jx ",
940d086b553STomohiro Kusumi 				       check_str, comp_str, cv64);
9417d565a4fSMatthew Dillon 			}
9425a790ddfSMatthew Dillon 			break;
9435a790ddfSMatthew Dillon 		case HAMMER2_CHECK_SHA192:
944bc8f6505STomohiro Kusumi 			SHA256_Init(&hash_ctx);
945bc8f6505STomohiro Kusumi 			SHA256_Update(&hash_ctx, &media, bytes);
946bc8f6505STomohiro Kusumi 			SHA256_Final(u.digest, &hash_ctx);
947bc8f6505STomohiro Kusumi 			u.digest64[2] ^= u.digest64[3];
948bc8f6505STomohiro Kusumi 			if (memcmp(u.digest, bref->check.sha192.data,
949bc8f6505STomohiro Kusumi 			    sizeof(bref->check.sha192.data))) {
950d086b553STomohiro Kusumi 				printf("(sha192 %s:%s failed) ",
951d086b553STomohiro Kusumi 				       check_str, comp_str);
952bc8f6505STomohiro Kusumi 				failed = 1;
953bc8f6505STomohiro Kusumi 			} else {
954d086b553STomohiro Kusumi 				printf("meth=%s|%s ", check_str, comp_str);
955bc8f6505STomohiro Kusumi 			}
9565a790ddfSMatthew Dillon 			break;
9575a790ddfSMatthew Dillon 		case HAMMER2_CHECK_FREEMAP:
9585a790ddfSMatthew Dillon 			cv = hammer2_icrc32(&media, bytes);
9595a790ddfSMatthew Dillon 			if (bref->check.freemap.icrc32 != cv) {
960d086b553STomohiro Kusumi 				printf("(fcrc %s|%s %08x/%08x failed) ",
961d086b553STomohiro Kusumi 					check_str, comp_str,
9625a790ddfSMatthew Dillon 					bref->check.freemap.icrc32,
9635a790ddfSMatthew Dillon 					cv);
96462a2c422SMatthew Dillon 				failed = 1;
9658adee7deSMatthew Dillon 			} else {
966d086b553STomohiro Kusumi 				printf("meth=%s|%s fcrc=%08x ",
967d086b553STomohiro Kusumi 					check_str, comp_str, cv);
9685a790ddfSMatthew Dillon 			}
9695a790ddfSMatthew Dillon 			break;
9705a790ddfSMatthew Dillon 		}
9715a790ddfSMatthew Dillon 	}
9725a790ddfSMatthew Dillon 
973aa2131f0SMatthew Dillon 	tab += show_tab;
974aa2131f0SMatthew Dillon 
975dd5e52caSTomohiro Kusumi 	if (QuietOpt > 0) {
976dd5e52caSTomohiro Kusumi 		obrace = 0;
977dd5e52caSTomohiro Kusumi 		printf("\n");
978dd5e52caSTomohiro Kusumi 		goto skip_data;
979dd5e52caSTomohiro Kusumi 	}
980dd5e52caSTomohiro Kusumi 
981dd5e52caSTomohiro Kusumi 	switch(bref->type) {
982bd878fc9SMatthew Dillon 	case HAMMER2_BREF_TYPE_EMPTY:
983660ecd92STomohiro Kusumi 		if (norecurse)
984660ecd92STomohiro Kusumi 			printf("\n");
985bd878fc9SMatthew Dillon 		obrace = 0;
986bd878fc9SMatthew Dillon 		break;
987da0cdd33SMatthew Dillon 	case HAMMER2_BREF_TYPE_DIRENT:
988da0cdd33SMatthew Dillon 		printf("{\n");
989da0cdd33SMatthew Dillon 		if (bref->embed.dirent.namlen <= sizeof(bref->check.buf)) {
990da0cdd33SMatthew Dillon 			tabprintf(tab, "filename \"%*.*s\"\n",
991da0cdd33SMatthew Dillon 				bref->embed.dirent.namlen,
992da0cdd33SMatthew Dillon 				bref->embed.dirent.namlen,
993da0cdd33SMatthew Dillon 				bref->check.buf);
994da0cdd33SMatthew Dillon 		} else {
995da0cdd33SMatthew Dillon 			tabprintf(tab, "filename \"%*.*s\"\n",
996da0cdd33SMatthew Dillon 				bref->embed.dirent.namlen,
997da0cdd33SMatthew Dillon 				bref->embed.dirent.namlen,
998da0cdd33SMatthew Dillon 				media.buf);
999da0cdd33SMatthew Dillon 		}
1000da0cdd33SMatthew Dillon 		tabprintf(tab, "inum 0x%016jx\n",
1001da0cdd33SMatthew Dillon 			  (uintmax_t)bref->embed.dirent.inum);
1002f168e7f9STomohiro Kusumi 		tabprintf(tab, "nlen %d\n", bref->embed.dirent.namlen);
1003da0cdd33SMatthew Dillon 		tabprintf(tab, "type %s\n",
1004da0cdd33SMatthew Dillon 			  hammer2_iptype_to_str(bref->embed.dirent.type));
1005da0cdd33SMatthew Dillon 		break;
1006bd878fc9SMatthew Dillon 	case HAMMER2_BREF_TYPE_INODE:
1007bd878fc9SMatthew Dillon 		printf("{\n");
1008b0f58de8SMatthew Dillon 		namelen = media.ipdata.meta.name_len;
1009ad7cf8eaSMatthew Dillon 		if (namelen > HAMMER2_INODE_MAXNAME)
1010ad7cf8eaSMatthew Dillon 			namelen = 0;
1011ad7cf8eaSMatthew Dillon 		tabprintf(tab, "filename \"%*.*s\"\n",
1012ad7cf8eaSMatthew Dillon 			  namelen, namelen, media.ipdata.filename);
1013b0f58de8SMatthew Dillon 		tabprintf(tab, "version  %d\n", media.ipdata.meta.version);
1014cac06d4eSTomohiro Kusumi 		if ((media.ipdata.meta.op_flags & HAMMER2_OPFLAG_PFSROOT) ||
1015cac06d4eSTomohiro Kusumi 		    media.ipdata.meta.pfs_type == HAMMER2_PFSTYPE_SUPROOT) {
1016cac06d4eSTomohiro Kusumi 			tabprintf(tab, "pfs_st   %d (%s)\n",
1017cac06d4eSTomohiro Kusumi 				  media.ipdata.meta.pfs_subtype,
1018cac06d4eSTomohiro Kusumi 				  hammer2_pfssubtype_to_str(media.ipdata.meta.pfs_subtype));
1019cac06d4eSTomohiro Kusumi 		}
1020bd878fc9SMatthew Dillon 		tabprintf(tab, "uflags   0x%08x\n",
1021b0f58de8SMatthew Dillon 			  media.ipdata.meta.uflags);
1022b0f58de8SMatthew Dillon 		if (media.ipdata.meta.rmajor || media.ipdata.meta.rminor) {
1023bd878fc9SMatthew Dillon 			tabprintf(tab, "rmajor   %d\n",
1024b0f58de8SMatthew Dillon 				  media.ipdata.meta.rmajor);
1025bd878fc9SMatthew Dillon 			tabprintf(tab, "rminor   %d\n",
1026b0f58de8SMatthew Dillon 				  media.ipdata.meta.rminor);
1027bd878fc9SMatthew Dillon 		}
1028bd878fc9SMatthew Dillon 		tabprintf(tab, "ctime    %s\n",
1029b0f58de8SMatthew Dillon 			  hammer2_time64_to_str(media.ipdata.meta.ctime, &str));
1030bd878fc9SMatthew Dillon 		tabprintf(tab, "mtime    %s\n",
1031b0f58de8SMatthew Dillon 			  hammer2_time64_to_str(media.ipdata.meta.mtime, &str));
1032bd878fc9SMatthew Dillon 		tabprintf(tab, "atime    %s\n",
1033b0f58de8SMatthew Dillon 			  hammer2_time64_to_str(media.ipdata.meta.atime, &str));
1034bd878fc9SMatthew Dillon 		tabprintf(tab, "btime    %s\n",
1035b0f58de8SMatthew Dillon 			  hammer2_time64_to_str(media.ipdata.meta.btime, &str));
1036bc092eefSTomohiro Kusumi 		uuid = media.ipdata.meta.uid;
1037bd878fc9SMatthew Dillon 		tabprintf(tab, "uid      %s\n",
1038bc092eefSTomohiro Kusumi 			  hammer2_uuid_to_str(&uuid, &str));
1039bc092eefSTomohiro Kusumi 		uuid = media.ipdata.meta.gid;
1040bd878fc9SMatthew Dillon 		tabprintf(tab, "gid      %s\n",
1041bc092eefSTomohiro Kusumi 			  hammer2_uuid_to_str(&uuid, &str));
1042bd878fc9SMatthew Dillon 		tabprintf(tab, "type     %s\n",
1043b0f58de8SMatthew Dillon 			  hammer2_iptype_to_str(media.ipdata.meta.type));
1044bd878fc9SMatthew Dillon 		tabprintf(tab, "opflgs   0x%02x\n",
1045b0f58de8SMatthew Dillon 			  media.ipdata.meta.op_flags);
1046bd878fc9SMatthew Dillon 		tabprintf(tab, "capflgs  0x%04x\n",
1047b0f58de8SMatthew Dillon 			  media.ipdata.meta.cap_flags);
1048bd878fc9SMatthew Dillon 		tabprintf(tab, "mode     %-7o\n",
1049b0f58de8SMatthew Dillon 			  media.ipdata.meta.mode);
1050bd878fc9SMatthew Dillon 		tabprintf(tab, "inum     0x%016jx\n",
1051b0f58de8SMatthew Dillon 			  media.ipdata.meta.inum);
105212404a28STomohiro Kusumi 		tabprintf(tab, "size     %ju ",
1053b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.size);
105412404a28STomohiro Kusumi 		if (media.ipdata.meta.op_flags & HAMMER2_OPFLAG_DIRECTDATA &&
105512404a28STomohiro Kusumi 		    media.ipdata.meta.size <= HAMMER2_EMBEDDED_BYTES)
105612404a28STomohiro Kusumi 			printf("(embedded data)\n");
105712404a28STomohiro Kusumi 		else
105812404a28STomohiro Kusumi 			printf("\n");
1059bd878fc9SMatthew Dillon 		tabprintf(tab, "nlinks   %ju\n",
1060b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.nlinks);
1061bd878fc9SMatthew Dillon 		tabprintf(tab, "iparent  0x%016jx\n",
1062b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.iparent);
1063bd878fc9SMatthew Dillon 		tabprintf(tab, "name_key 0x%016jx\n",
1064b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.name_key);
1065bd878fc9SMatthew Dillon 		tabprintf(tab, "name_len %u\n",
1066b0f58de8SMatthew Dillon 			  media.ipdata.meta.name_len);
1067bd878fc9SMatthew Dillon 		tabprintf(tab, "ncopies  %u\n",
1068b0f58de8SMatthew Dillon 			  media.ipdata.meta.ncopies);
10692a98b0e0STomohiro Kusumi 		tabprintf(tab, "compalg  %s\n",
10702a98b0e0STomohiro Kusumi 			  hammer2_compmode_to_str(media.ipdata.meta.comp_algo));
10712a98b0e0STomohiro Kusumi 		tabprintf(tab, "checkalg %s\n",
10722a98b0e0STomohiro Kusumi 			  hammer2_checkmode_to_str(media.ipdata.meta.check_algo));
1073b7add675SMatthew Dillon 		if ((media.ipdata.meta.op_flags & HAMMER2_OPFLAG_PFSROOT) ||
1074b7add675SMatthew Dillon 		    media.ipdata.meta.pfs_type == HAMMER2_PFSTYPE_SUPROOT) {
107512404a28STomohiro Kusumi 			tabprintf(tab, "pfs_nmas %u\n",
107612404a28STomohiro Kusumi 				  media.ipdata.meta.pfs_nmasters);
1077bd878fc9SMatthew Dillon 			tabprintf(tab, "pfs_type %u (%s)\n",
1078b0f58de8SMatthew Dillon 				  media.ipdata.meta.pfs_type,
1079b0f58de8SMatthew Dillon 				  hammer2_pfstype_to_str(media.ipdata.meta.pfs_type));
1080bd878fc9SMatthew Dillon 			tabprintf(tab, "pfs_inum 0x%016jx\n",
1081b0f58de8SMatthew Dillon 				  (uintmax_t)media.ipdata.meta.pfs_inum);
1082bc092eefSTomohiro Kusumi 			uuid = media.ipdata.meta.pfs_clid;
10838c280d5dSMatthew Dillon 			tabprintf(tab, "pfs_clid %s\n",
1084bc092eefSTomohiro Kusumi 				  hammer2_uuid_to_str(&uuid, &str));
1085bc092eefSTomohiro Kusumi 			uuid = media.ipdata.meta.pfs_fsid;
1086bd878fc9SMatthew Dillon 			tabprintf(tab, "pfs_fsid %s\n",
1087bc092eefSTomohiro Kusumi 				  hammer2_uuid_to_str(&uuid, &str));
10887866a0e7SMatthew Dillon 			tabprintf(tab, "pfs_lsnap_tid 0x%016jx\n",
10897866a0e7SMatthew Dillon 				  (uintmax_t)media.ipdata.meta.pfs_lsnap_tid);
1090bd878fc9SMatthew Dillon 		}
1091bd878fc9SMatthew Dillon 		tabprintf(tab, "data_quota  %ju\n",
1092b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.data_quota);
1093bd878fc9SMatthew Dillon 		tabprintf(tab, "data_count  %ju\n",
1094da0cdd33SMatthew Dillon 			  (uintmax_t)bref->embed.stats.data_count);
1095bd878fc9SMatthew Dillon 		tabprintf(tab, "inode_quota %ju\n",
1096b0f58de8SMatthew Dillon 			  (uintmax_t)media.ipdata.meta.inode_quota);
1097bd878fc9SMatthew Dillon 		tabprintf(tab, "inode_count %ju\n",
1098da0cdd33SMatthew Dillon 			  (uintmax_t)bref->embed.stats.inode_count);
1099bd878fc9SMatthew Dillon 		break;
1100bd878fc9SMatthew Dillon 	case HAMMER2_BREF_TYPE_INDIRECT:
1101bd878fc9SMatthew Dillon 		printf("{\n");
1102bd878fc9SMatthew Dillon 		break;
1103bd878fc9SMatthew Dillon 	case HAMMER2_BREF_TYPE_DATA:
1104bd878fc9SMatthew Dillon 		printf("\n");
1105bd878fc9SMatthew Dillon 		obrace = 0;
1106bd878fc9SMatthew Dillon 		break;
1107bd878fc9SMatthew Dillon 	case HAMMER2_BREF_TYPE_VOLUME:
110850456506SMatthew Dillon 		printf("mirror_tid=%016jx freemap_tid=%016jx ",
110950456506SMatthew Dillon 			media.voldata.mirror_tid,
111010136ab6SMatthew Dillon 			media.voldata.freemap_tid);
1111208afee5STomohiro Kusumi 		printf("{\n");
1112208afee5STomohiro Kusumi 		break;
1113208afee5STomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP:
1114208afee5STomohiro Kusumi 		printf("mirror_tid=%016jx freemap_tid=%016jx ",
1115208afee5STomohiro Kusumi 			media.voldata.mirror_tid,
1116208afee5STomohiro Kusumi 			media.voldata.freemap_tid);
1117bd878fc9SMatthew Dillon 		printf("{\n");
1118bd878fc9SMatthew Dillon 		break;
111978ac5385SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
112093f3933aSMatthew Dillon 		printf("{\n");
1121906f9d76STomohiro Kusumi 		tmp = bref->data_off & ~HAMMER2_OFF_MASK_RADIX;
1122906f9d76STomohiro Kusumi 		tmp &= HAMMER2_SEGMASK;
1123906f9d76STomohiro Kusumi 		tmp /= HAMMER2_PBUFSIZE;
1124ae495466STomohiro Kusumi 		assert(tmp >= HAMMER2_ZONE_FREEMAP_00);
1125906f9d76STomohiro Kusumi 		assert(tmp < HAMMER2_ZONE_FREEMAP_END);
1126906f9d76STomohiro Kusumi 		tmp -= HAMMER2_ZONE_FREEMAP_00;
1127906f9d76STomohiro Kusumi 		tmp /= HAMMER2_ZONE_FREEMAP_INC;
1128906f9d76STomohiro Kusumi 		tabprintf(tab, "rotation=%d\n", (int)tmp);
1129906f9d76STomohiro Kusumi 
113093f3933aSMatthew Dillon 		for (i = 0; i < HAMMER2_FREEMAP_COUNT; ++i) {
113179e82fbcSTomohiro Kusumi 			hammer2_off_t data_off = bref->key +
113243c0f951STomohiro Kusumi 				i * HAMMER2_FREEMAP_LEVEL0_SIZE;
11335cebbe36SMatthew Dillon #if HAMMER2_BMAP_ELEMENTS != 8
11345cebbe36SMatthew Dillon #error "cmd_debug.c: HAMMER2_BMAP_ELEMENTS expected to be 8"
11355cebbe36SMatthew Dillon #endif
113666b8e023STomohiro Kusumi 			tabprintf(tab + 4, "%016jx %04d.%04x linear=%06x avail=%06x "
11375cebbe36SMatthew Dillon 				  "%016jx %016jx %016jx %016jx "
11385cebbe36SMatthew Dillon 				  "%016jx %016jx %016jx %016jx\n",
113979e82fbcSTomohiro Kusumi 				  data_off, i, media.bmdata[i].class,
114066b8e023STomohiro Kusumi 				  media.bmdata[i].linear,
114193f3933aSMatthew Dillon 				  media.bmdata[i].avail,
11425cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[0],
11435cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[1],
11445cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[2],
11455cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[3],
11465cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[4],
11475cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[5],
11485cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[6],
11495cebbe36SMatthew Dillon 				  media.bmdata[i].bitmapq[7]);
11505c37bf12SMatthew Dillon 		}
115193f3933aSMatthew Dillon 		tabprintf(tab, "}\n");
115278ac5385SMatthew Dillon 		break;
115378ac5385SMatthew Dillon 	case HAMMER2_BREF_TYPE_FREEMAP_NODE:
115478ac5385SMatthew Dillon 		printf("{\n");
1155906f9d76STomohiro Kusumi 		tmp = bref->data_off & ~HAMMER2_OFF_MASK_RADIX;
1156906f9d76STomohiro Kusumi 		tmp &= HAMMER2_SEGMASK;
1157906f9d76STomohiro Kusumi 		tmp /= HAMMER2_PBUFSIZE;
1158ae495466STomohiro Kusumi 		assert(tmp >= HAMMER2_ZONE_FREEMAP_00);
1159906f9d76STomohiro Kusumi 		assert(tmp < HAMMER2_ZONE_FREEMAP_END);
1160906f9d76STomohiro Kusumi 		tmp -= HAMMER2_ZONE_FREEMAP_00;
1161906f9d76STomohiro Kusumi 		tmp /= HAMMER2_ZONE_FREEMAP_INC;
1162906f9d76STomohiro Kusumi 		tabprintf(tab, "rotation=%d\n", (int)tmp);
116378ac5385SMatthew Dillon 		break;
1164bd878fc9SMatthew Dillon 	default:
116578ac5385SMatthew Dillon 		printf("\n");
116678ac5385SMatthew Dillon 		obrace = 0;
1167bd878fc9SMatthew Dillon 		break;
1168bd878fc9SMatthew Dillon 	}
1169bd878fc9SMatthew Dillon 	if (str)
1170bd878fc9SMatthew Dillon 		free(str);
117162a2c422SMatthew Dillon 
1172dd5e52caSTomohiro Kusumi skip_data:
117362a2c422SMatthew Dillon 	/*
1174db2a354aSTomohiro Kusumi 	 * Update statistics.
1175db2a354aSTomohiro Kusumi 	 */
1176db2a354aSTomohiro Kusumi 	switch(bref->type) {
1177db2a354aSTomohiro Kusumi 	case HAMMER2_BREF_TYPE_FREEMAP_LEAF:
1178db2a354aSTomohiro Kusumi 		for (i = 0; i < HAMMER2_FREEMAP_COUNT; ++i) {
1179db2a354aSTomohiro Kusumi 			hammer2_off_t data_off = bref->key +
1180db2a354aSTomohiro Kusumi 				i * HAMMER2_FREEMAP_LEVEL0_SIZE;
1181db2a354aSTomohiro Kusumi 			if (data_off >= voldata->aux_end &&
11820b738157STomohiro Kusumi 			    data_off < hammer2_get_total_size()) {
1183db2a354aSTomohiro Kusumi 				int j;
1184db2a354aSTomohiro Kusumi 				for (j = 0; j < 4; ++j)
11856c129444STomohiro Kusumi 					count_blocks(&media.bmdata[i], j,
1186db2a354aSTomohiro Kusumi 						    &TotalAccum16[j],
1187db2a354aSTomohiro Kusumi 						    &TotalAccum64[j]);
1188db2a354aSTomohiro Kusumi 			} else
1189db2a354aSTomohiro Kusumi 				TotalUnavail += HAMMER2_FREEMAP_LEVEL0_SIZE;
1190db2a354aSTomohiro Kusumi 		}
1191db2a354aSTomohiro Kusumi 		TotalFreemap += HAMMER2_FREEMAP_LEVEL1_SIZE;
1192db2a354aSTomohiro Kusumi 		break;
1193db2a354aSTomohiro Kusumi 	default:
1194db2a354aSTomohiro Kusumi 		break;
1195db2a354aSTomohiro Kusumi 	}
1196db2a354aSTomohiro Kusumi 
1197db2a354aSTomohiro Kusumi 	/*
119862a2c422SMatthew Dillon 	 * Recurse if norecurse == 0.  If the CRC failed, pass norecurse = 1.
119962a2c422SMatthew Dillon 	 * That is, if an indirect or inode fails we still try to list its
120062a2c422SMatthew Dillon 	 * direct children to help with debugging, but go no further than
120162a2c422SMatthew Dillon 	 * that because they are probably garbage.
120262a2c422SMatthew Dillon 	 */
120391e93d9fSTomohiro Kusumi 	if (show_depth == -1 || ((tab - init_tab) / show_tab) < show_depth) {
120462a2c422SMatthew Dillon 		for (i = 0; norecurse == 0 && i < bcount; ++i) {
1205bd878fc9SMatthew Dillon 			if (bscan[i].type != HAMMER2_BREF_TYPE_EMPTY) {
12060b738157STomohiro Kusumi 				show_bref(voldata, tab, i, &bscan[i],
120791e93d9fSTomohiro Kusumi 				    failed);
120891e93d9fSTomohiro Kusumi 			}
1209bd878fc9SMatthew Dillon 		}
1210bd878fc9SMatthew Dillon 	}
12118ca87c4cSTomohiro Kusumi 	tab -= show_tab;
1212bd878fc9SMatthew Dillon 	if (obrace) {
1213bd878fc9SMatthew Dillon 		if (bref->type == HAMMER2_BREF_TYPE_INODE)
12141fca819aSMatthew Dillon 			tabprintf(tab, "} (%s.%d, \"%*.*s\")\n",
121579e82fbcSTomohiro Kusumi 				  type_str, bi, namelen, namelen,
121679e82fbcSTomohiro Kusumi 				  media.ipdata.filename);
1217bd878fc9SMatthew Dillon 		else
1218bd878fc9SMatthew Dillon 			tabprintf(tab, "} (%s.%d)\n", type_str, bi);
1219bd878fc9SMatthew Dillon 	}
1220bd878fc9SMatthew Dillon }
1221bd878fc9SMatthew Dillon 
12225c37bf12SMatthew Dillon static
12235c37bf12SMatthew Dillon void
count_blocks(hammer2_bmap_data_t * bmap,int value,hammer2_off_t * accum16,hammer2_off_t * accum64)12246c129444STomohiro Kusumi count_blocks(hammer2_bmap_data_t *bmap, int value,
12255c37bf12SMatthew Dillon 	     hammer2_off_t *accum16, hammer2_off_t *accum64)
12265c37bf12SMatthew Dillon {
1227ce550745STomohiro Kusumi 	int i, j, bits;
1228ce550745STomohiro Kusumi 	hammer2_bitmap_t value16, value64;
1229ce550745STomohiro Kusumi 
1230ce550745STomohiro Kusumi 	bits = (int)sizeof(hammer2_bitmap_t) * 8;
123122f08f81STomohiro Kusumi 	assert(bits == 64);
12325c37bf12SMatthew Dillon 
1233ce550745STomohiro Kusumi 	value16 = value;
1234ce550745STomohiro Kusumi 	assert(value16 < 4);
1235ce550745STomohiro Kusumi 	value64 = (value16 << 6) | (value16 << 4) | (value16 << 2) | value16;
1236ce550745STomohiro Kusumi 	assert(value64 < 256);
1237ce550745STomohiro Kusumi 
123822f08f81STomohiro Kusumi 	for (i = 0; i < HAMMER2_BMAP_ELEMENTS; ++i) {
123922f08f81STomohiro Kusumi 		hammer2_bitmap_t bm = bmap->bitmapq[i];
124022f08f81STomohiro Kusumi 		hammer2_bitmap_t bm_save = bm;
124122f08f81STomohiro Kusumi 		hammer2_bitmap_t mask;
12425c37bf12SMatthew Dillon 
124322f08f81STomohiro Kusumi 		mask = 0x03; /* 2 bits per 16KB */
124422f08f81STomohiro Kusumi 		for (j = 0; j < bits; j += 2) {
1245ce550745STomohiro Kusumi 			if ((bm & mask) == value16)
12465c37bf12SMatthew Dillon 				*accum16 += 16384;
1247dfc6e32eSTomohiro Kusumi 			bm >>= 2;
12485c37bf12SMatthew Dillon 		}
1249dfc6e32eSTomohiro Kusumi 
1250dfc6e32eSTomohiro Kusumi 		bm = bm_save;
125122f08f81STomohiro Kusumi 		mask = 0xFF; /* 8 bits per 64KB chunk */
125222f08f81STomohiro Kusumi 		for (j = 0; j < bits; j += 8) {
1253ce550745STomohiro Kusumi 			if ((bm & mask) == value64)
12545c37bf12SMatthew Dillon 				*accum64 += 65536;
1255dfc6e32eSTomohiro Kusumi 			bm >>= 8;
12565c37bf12SMatthew Dillon 		}
12575c37bf12SMatthew Dillon 	}
12585c37bf12SMatthew Dillon }
12595c37bf12SMatthew Dillon 
1260775153c2SMatthew Dillon int
cmd_hash(int ac,const char ** av)1261775153c2SMatthew Dillon cmd_hash(int ac, const char **av)
1262775153c2SMatthew Dillon {
1263775153c2SMatthew Dillon 	int i;
1264775153c2SMatthew Dillon 
1265775153c2SMatthew Dillon 	for (i = 0; i < ac; ++i) {
12667b6e3143STomohiro Kusumi 		printf("%016jx %s\n",
12671d5238a4STomohiro Kusumi 		       dirhash(av[i], strlen(av[i])),
12687b6e3143STomohiro Kusumi 		       av[i]);
1269775153c2SMatthew Dillon 	}
1270775153c2SMatthew Dillon 	return(0);
1271775153c2SMatthew Dillon }
1272775153c2SMatthew Dillon 
12738f579e46SMatthew Dillon int
cmd_dhash(int ac,const char ** av)12740c41f055SMatthew Dillon cmd_dhash(int ac, const char **av)
12750c41f055SMatthew Dillon {
12760c41f055SMatthew Dillon 	char buf[1024];		/* 1K extended directory record */
12770c41f055SMatthew Dillon 	uint64_t hash;
12780c41f055SMatthew Dillon 	int i;
12790c41f055SMatthew Dillon 
12800c41f055SMatthew Dillon 	for (i = 0; i < ac; ++i) {
12810c41f055SMatthew Dillon 		bzero(buf, sizeof(buf));
12820c41f055SMatthew Dillon 		snprintf(buf, sizeof(buf), "%s", av[i]);
12830c41f055SMatthew Dillon 		hash = XXH64(buf, sizeof(buf), XXH_HAMMER2_SEED);
12840c41f055SMatthew Dillon 		printf("%016jx %s\n", hash, av[i]);
12850c41f055SMatthew Dillon 	}
12860c41f055SMatthew Dillon 	return(0);
12870c41f055SMatthew Dillon }
12880c41f055SMatthew Dillon 
12890c41f055SMatthew Dillon int
cmd_dumpchain(const char * path,u_int flags)129040498d1cSMatthew Dillon cmd_dumpchain(const char *path, u_int flags)
12918f579e46SMatthew Dillon {
129240498d1cSMatthew Dillon 	int dummy = (int)flags;
129397ea1536STomohiro Kusumi 	int ecode = 0;
12948f579e46SMatthew Dillon 	int fd;
12958f579e46SMatthew Dillon 
12968f579e46SMatthew Dillon 	fd = open(path, O_RDONLY);
12978f579e46SMatthew Dillon 	if (fd >= 0) {
129897ea1536STomohiro Kusumi 		if (ioctl(fd, HAMMER2IOC_DEBUG_DUMP, &dummy) < 0) {
129997ea1536STomohiro Kusumi 			fprintf(stderr, "%s: %s\n", path, strerror(errno));
130097ea1536STomohiro Kusumi 			ecode = 1;
130197ea1536STomohiro Kusumi 		}
13028f579e46SMatthew Dillon 		close(fd);
13038f579e46SMatthew Dillon 	} else {
13048f579e46SMatthew Dillon 		fprintf(stderr, "unable to open %s\n", path);
130597ea1536STomohiro Kusumi 		ecode = 1;
13068f579e46SMatthew Dillon 	}
130797ea1536STomohiro Kusumi 	return ecode;
13088f579e46SMatthew Dillon }
13098f579e46SMatthew Dillon 
1310bd878fc9SMatthew Dillon static
1311bd878fc9SMatthew Dillon void
tabprintf(int tab,const char * ctl,...)1312bd878fc9SMatthew Dillon tabprintf(int tab, const char *ctl, ...)
1313bd878fc9SMatthew Dillon {
1314bd878fc9SMatthew Dillon 	va_list va;
1315bd878fc9SMatthew Dillon 
1316bd878fc9SMatthew Dillon 	printf("%*.*s", tab, tab, "");
1317bd878fc9SMatthew Dillon 	va_start(va, ctl);
1318bd878fc9SMatthew Dillon 	vprintf(ctl, va);
1319bd878fc9SMatthew Dillon 	va_end(va);
1320bd878fc9SMatthew Dillon }
1321