xref: /dragonfly/sbin/hammer/hammer.c (revision 69f5a58c)
10dfeb6c8SMatthew Dillon /*
20dfeb6c8SMatthew Dillon  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
30dfeb6c8SMatthew Dillon  *
40dfeb6c8SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
50dfeb6c8SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
60dfeb6c8SMatthew Dillon  *
70dfeb6c8SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
80dfeb6c8SMatthew Dillon  * modification, are permitted provided that the following conditions
90dfeb6c8SMatthew Dillon  * are met:
100dfeb6c8SMatthew Dillon  *
110dfeb6c8SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
120dfeb6c8SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
130dfeb6c8SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
140dfeb6c8SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
150dfeb6c8SMatthew Dillon  *    the documentation and/or other materials provided with the
160dfeb6c8SMatthew Dillon  *    distribution.
170dfeb6c8SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
180dfeb6c8SMatthew Dillon  *    contributors may be used to endorse or promote products derived
190dfeb6c8SMatthew Dillon  *    from this software without specific, prior written permission.
200dfeb6c8SMatthew Dillon  *
210dfeb6c8SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
220dfeb6c8SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
230dfeb6c8SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
240dfeb6c8SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
250dfeb6c8SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
260dfeb6c8SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
270dfeb6c8SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
280dfeb6c8SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
290dfeb6c8SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
300dfeb6c8SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
310dfeb6c8SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
320dfeb6c8SMatthew Dillon  * SUCH DAMAGE.
330dfeb6c8SMatthew Dillon  *
34de1c0b31SMatthew Dillon  * $DragonFly: src/sbin/hammer/hammer.c,v 1.44 2008/11/13 02:04:27 dillon Exp $
350dfeb6c8SMatthew Dillon  */
360dfeb6c8SMatthew Dillon 
3761aeeb33SMatthew Dillon #include "hammer.h"
380006adaeSMatthew Dillon #include <signal.h>
39d71afe7bSMatthew Dillon #include <math.h>
409c9ac2f1SMatthew Dillon #include <fstab.h>
410dfeb6c8SMatthew Dillon 
42d38ab092SMatthew Dillon static void hammer_parsedevs(const char *blkdevs);
430006adaeSMatthew Dillon static void sigalrm(int signo);
44445faa69SMatthew Dillon static void sigintr(int signo);
450dfeb6c8SMatthew Dillon static void usage(int exit_code);
460dfeb6c8SMatthew Dillon 
47d38ab092SMatthew Dillon int RecurseOpt;
48563b4845SMatthew Dillon int VerboseOpt;
49e95314deSMatthew Dillon int QuietOpt;
50d71afe7bSMatthew Dillon int NoSyncOpt;
51243ca327SMatthew Dillon int TwoWayPipeOpt;
52243ca327SMatthew Dillon int TimeoutOpt;
5348eadef9SMatthew Dillon int DelayOpt = 5;
546c45ca3eSMatthew Dillon char *SshPort;
5507485271SMichael Neumann int ForceYesOpt = 0;
563a998207SMatthew Dillon int CompressOpt;
57e7f926a5SMatthew Dillon int ForceOpt;
58445faa69SMatthew Dillon int RunningIoctl;
59445faa69SMatthew Dillon int DidInterrupt;
600bd7a37cSMatthew Dillon int BulkOpt;
6148eadef9SMatthew Dillon u_int64_t BandwidthOpt;
62527a7bdbSMatthew Dillon u_int64_t SplitupOpt = 4ULL * 1024ULL * 1024ULL * 1024ULL;
63fbe1c665SMatthew Dillon u_int64_t MemoryLimit = 1024LLU * 1024 * 1024;
64b6ced256SMatthew Dillon const char *SplitupOptStr;
65d7ae405cSMatthew Dillon const char *CyclePath;
66da804f11SMatthew Dillon const char *LinkPath;
67*69f5a58cSMatthew Dillon const char *RestrictTarget;
68d38ab092SMatthew Dillon 
690dfeb6c8SMatthew Dillon int
700dfeb6c8SMatthew Dillon main(int ac, char **av)
710dfeb6c8SMatthew Dillon {
72d38ab092SMatthew Dillon 	char *blkdevs = NULL;
7348eadef9SMatthew Dillon 	char *ptr;
74*69f5a58cSMatthew Dillon 	char *restrictcmd = NULL;
7548eadef9SMatthew Dillon 	u_int32_t status;
7648eadef9SMatthew Dillon 	int ch;
770faa08a1SMatthew Dillon 	int cacheSize = 0;
780dfeb6c8SMatthew Dillon 
79269cdd19SMatthew Dillon 	while ((ch = getopt(ac, av,
80*69f5a58cSMatthew Dillon 			    "b:c:de:hf:i:m:p:qrs:t:v2yBC:FR:S:T:X")) != -1) {
810dfeb6c8SMatthew Dillon 		switch(ch) {
82243ca327SMatthew Dillon 		case '2':
83243ca327SMatthew Dillon 			TwoWayPipeOpt = 1;
84243ca327SMatthew Dillon 			break;
8507485271SMichael Neumann 		case 'y':
8607485271SMichael Neumann 			ForceYesOpt = 1;
8707485271SMichael Neumann 			break;
8848eadef9SMatthew Dillon 		case 'b':
8948eadef9SMatthew Dillon 			BandwidthOpt = strtoull(optarg, &ptr, 0);
9048eadef9SMatthew Dillon 			switch(*ptr) {
9148eadef9SMatthew Dillon 			case 'g':
9248eadef9SMatthew Dillon 			case 'G':
9348eadef9SMatthew Dillon 				BandwidthOpt *= 1024;
9448eadef9SMatthew Dillon 				/* fall through */
9548eadef9SMatthew Dillon 			case 'm':
9648eadef9SMatthew Dillon 			case 'M':
9748eadef9SMatthew Dillon 				BandwidthOpt *= 1024;
9848eadef9SMatthew Dillon 				/* fall through */
9948eadef9SMatthew Dillon 			case 'k':
10048eadef9SMatthew Dillon 			case 'K':
10148eadef9SMatthew Dillon 				BandwidthOpt *= 1024;
10248eadef9SMatthew Dillon 				break;
103224ac2f2SMatthew Dillon 			case '\0':
104224ac2f2SMatthew Dillon 				/* bytes per second if no suffix */
105224ac2f2SMatthew Dillon 				break;
10648eadef9SMatthew Dillon 			default:
10748eadef9SMatthew Dillon 				usage(1);
10848eadef9SMatthew Dillon 			}
10948eadef9SMatthew Dillon 			break;
1103d7b2393SMatthew Dillon 		case 'S':
111b6ced256SMatthew Dillon 			SplitupOptStr = strdup(optarg);
1123d7b2393SMatthew Dillon 			SplitupOpt = strtoull(optarg, &ptr, 0);
1133d7b2393SMatthew Dillon 			switch(*ptr) {
1143d7b2393SMatthew Dillon 			case 'g':
1153d7b2393SMatthew Dillon 			case 'G':
1163d7b2393SMatthew Dillon 				SplitupOpt *= 1024;
1173d7b2393SMatthew Dillon 				/* fall through */
1183d7b2393SMatthew Dillon 			case 'm':
1193d7b2393SMatthew Dillon 			case 'M':
1203d7b2393SMatthew Dillon 				SplitupOpt *= 1024;
1213d7b2393SMatthew Dillon 				/* fall through */
1223d7b2393SMatthew Dillon 			case 'k':
1233d7b2393SMatthew Dillon 			case 'K':
1243d7b2393SMatthew Dillon 				SplitupOpt *= 1024;
1253d7b2393SMatthew Dillon 				break;
1263d7b2393SMatthew Dillon 			case '\0':
1273d7b2393SMatthew Dillon 				/* bytes per second if no suffix */
1283d7b2393SMatthew Dillon 				break;
1293d7b2393SMatthew Dillon 			default:
1303d7b2393SMatthew Dillon 				usage(1);
1313d7b2393SMatthew Dillon 			}
1323d7b2393SMatthew Dillon 			break;
133d7ae405cSMatthew Dillon 		case 'c':
134d7ae405cSMatthew Dillon 			CyclePath = optarg;
135d7ae405cSMatthew Dillon 			break;
136ba7b52c9SMatthew Dillon 		case 'd':
137ba7b52c9SMatthew Dillon 			++DebugOpt;
138ba7b52c9SMatthew Dillon 			break;
139269cdd19SMatthew Dillon 		case 'e':
140269cdd19SMatthew Dillon 			ScoreBoardFile = optarg;
141269cdd19SMatthew Dillon 			break;
1420dfeb6c8SMatthew Dillon 		case 'h':
1430dfeb6c8SMatthew Dillon 			usage(0);
1440dfeb6c8SMatthew Dillon 			/* not reached */
14548eadef9SMatthew Dillon 		case 'i':
14648eadef9SMatthew Dillon 			DelayOpt = strtol(optarg, NULL, 0);
14748eadef9SMatthew Dillon 			break;
148fbe1c665SMatthew Dillon 		case 'm':
149fbe1c665SMatthew Dillon 			MemoryLimit = strtouq(optarg, &ptr, 0);
150fbe1c665SMatthew Dillon 			switch(*ptr) {
151fbe1c665SMatthew Dillon 			case 't':
152fbe1c665SMatthew Dillon 			case 'T':
153fbe1c665SMatthew Dillon 				MemoryLimit *= 1024;
154fbe1c665SMatthew Dillon 				/* fall through */
155fbe1c665SMatthew Dillon 			case 'g':
156fbe1c665SMatthew Dillon 			case 'G':
157fbe1c665SMatthew Dillon 				MemoryLimit *= 1024;
158fbe1c665SMatthew Dillon 				/* fall through */
159fbe1c665SMatthew Dillon 			case 'm':
160fbe1c665SMatthew Dillon 			case 'M':
161fbe1c665SMatthew Dillon 				MemoryLimit *= 1024;
162fbe1c665SMatthew Dillon 				/* fall through */
163fbe1c665SMatthew Dillon 			case 'k':
164fbe1c665SMatthew Dillon 			case 'K':
165fbe1c665SMatthew Dillon 				MemoryLimit *= 1024;
166fbe1c665SMatthew Dillon 				/* fall through */
167fbe1c665SMatthew Dillon 			default:
168fbe1c665SMatthew Dillon 				break;
169fbe1c665SMatthew Dillon 			}
170fbe1c665SMatthew Dillon 
171fbe1c665SMatthew Dillon 			/* minimum limit */
172fbe1c665SMatthew Dillon 			if (MemoryLimit < 1024 * 1024)
173fbe1c665SMatthew Dillon 				MemoryLimit = 1024 * 1024;
174fbe1c665SMatthew Dillon 			break;
1756c45ca3eSMatthew Dillon 		case 'p':
1766c45ca3eSMatthew Dillon 			SshPort = optarg;
1776c45ca3eSMatthew Dillon 			break;
178d38ab092SMatthew Dillon 		case 'r':
179d38ab092SMatthew Dillon 			RecurseOpt = 1;
180d38ab092SMatthew Dillon 			break;
181d38ab092SMatthew Dillon 		case 'f':
182d38ab092SMatthew Dillon 			blkdevs = optarg;
183d38ab092SMatthew Dillon 			break;
184da804f11SMatthew Dillon 		case 's':
185da804f11SMatthew Dillon 			LinkPath = optarg;
186da804f11SMatthew Dillon 			break;
1870006adaeSMatthew Dillon 		case 't':
188243ca327SMatthew Dillon 			TimeoutOpt = strtol(optarg, NULL, 0);
1890006adaeSMatthew Dillon 			break;
190563b4845SMatthew Dillon 		case 'v':
191e95314deSMatthew Dillon 			if (QuietOpt > 0)
192e95314deSMatthew Dillon 				--QuietOpt;
193e95314deSMatthew Dillon 			else
194563b4845SMatthew Dillon 				++VerboseOpt;
195563b4845SMatthew Dillon 			break;
196e95314deSMatthew Dillon 		case 'q':
197e95314deSMatthew Dillon 			if (VerboseOpt > 0)
198e95314deSMatthew Dillon 				--VerboseOpt;
199e95314deSMatthew Dillon 			else
200e95314deSMatthew Dillon 				++QuietOpt;
201e95314deSMatthew Dillon 			break;
2020bd7a37cSMatthew Dillon 		case 'B':
2030bd7a37cSMatthew Dillon 			BulkOpt = 1;
2040bd7a37cSMatthew Dillon 			break;
2050faa08a1SMatthew Dillon 		case 'C':
2060faa08a1SMatthew Dillon 			cacheSize = strtol(optarg, &ptr, 0);
2070faa08a1SMatthew Dillon 			switch(*ptr) {
2080faa08a1SMatthew Dillon 			case 'm':
2090faa08a1SMatthew Dillon 			case 'M':
2100faa08a1SMatthew Dillon 				cacheSize *= 1024;
2110faa08a1SMatthew Dillon 				/* fall through */
2120faa08a1SMatthew Dillon 			case 'k':
2130faa08a1SMatthew Dillon 			case 'K':
2140faa08a1SMatthew Dillon 				cacheSize *= 1024;
215b46b99bfSMatthew Dillon 				++ptr;
2160faa08a1SMatthew Dillon 				break;
2170faa08a1SMatthew Dillon 			case '\0':
218b46b99bfSMatthew Dillon 			case ':':
2190faa08a1SMatthew Dillon 				/* bytes if no suffix */
2200faa08a1SMatthew Dillon 				break;
2210faa08a1SMatthew Dillon 			default:
2220faa08a1SMatthew Dillon 				usage(1);
2230faa08a1SMatthew Dillon 			}
224b46b99bfSMatthew Dillon 			if (*ptr == ':') {
225b46b99bfSMatthew Dillon 				UseReadAhead = strtol(ptr + 1, NULL, 0);
226b46b99bfSMatthew Dillon 				UseReadBehind = -UseReadAhead;
227b46b99bfSMatthew Dillon 			}
2280faa08a1SMatthew Dillon 			if (cacheSize < 1024 * 1024)
2290faa08a1SMatthew Dillon 				cacheSize = 1024 * 1024;
230b46b99bfSMatthew Dillon 			if (UseReadAhead < 0)
231b46b99bfSMatthew Dillon 				usage(1);
232b46b99bfSMatthew Dillon 			if (UseReadAhead * HAMMER_BUFSIZE / cacheSize / 16) {
233b46b99bfSMatthew Dillon 				UseReadAhead = cacheSize / 16 / HAMMER_BUFSIZE;
234b46b99bfSMatthew Dillon 				UseReadBehind = -UseReadAhead;
235b46b99bfSMatthew Dillon 			}
2360faa08a1SMatthew Dillon 			hammer_cache_set(cacheSize);
2370faa08a1SMatthew Dillon 			break;
238e7f926a5SMatthew Dillon 		case 'F':
239e7f926a5SMatthew Dillon 			ForceOpt = 1;
240e7f926a5SMatthew Dillon 			break;
241*69f5a58cSMatthew Dillon 		case 'R':
242*69f5a58cSMatthew Dillon 			if (restrictcmd == NULL)
243*69f5a58cSMatthew Dillon 				restrictcmd = optarg;
244*69f5a58cSMatthew Dillon 			break;
245*69f5a58cSMatthew Dillon 		case 'T':
246*69f5a58cSMatthew Dillon 			if (RestrictTarget == NULL)
247*69f5a58cSMatthew Dillon 				RestrictTarget = optarg;
248*69f5a58cSMatthew Dillon 			break;
2493a998207SMatthew Dillon 		case 'X':
2503a998207SMatthew Dillon 			CompressOpt = 1;
2513a998207SMatthew Dillon 			break;
2520dfeb6c8SMatthew Dillon 		default:
2530dfeb6c8SMatthew Dillon 			usage(1);
2540dfeb6c8SMatthew Dillon 			/* not reached */
2550dfeb6c8SMatthew Dillon 		}
2560dfeb6c8SMatthew Dillon 	}
2570dfeb6c8SMatthew Dillon 	ac -= optind;
2580dfeb6c8SMatthew Dillon 	av += optind;
2590dfeb6c8SMatthew Dillon 	if (ac < 1) {
2600dfeb6c8SMatthew Dillon 		usage(1);
2610dfeb6c8SMatthew Dillon 		/* not reached */
2620dfeb6c8SMatthew Dillon 	}
2630dfeb6c8SMatthew Dillon 
2640006adaeSMatthew Dillon 	signal(SIGALRM, sigalrm);
265445faa69SMatthew Dillon 	signal(SIGINT, sigintr);
2660006adaeSMatthew Dillon 
267*69f5a58cSMatthew Dillon 	/*
268*69f5a58cSMatthew Dillon 	 * Check command restriction (used by hammer ssh-remote).  Several
269*69f5a58cSMatthew Dillon 	 * commands may be iterated with a comma.
270*69f5a58cSMatthew Dillon 	 */
271*69f5a58cSMatthew Dillon 	if (restrictcmd) {
272*69f5a58cSMatthew Dillon 		char *elm;
273*69f5a58cSMatthew Dillon 
274*69f5a58cSMatthew Dillon 		ptr = strdup(restrictcmd);
275*69f5a58cSMatthew Dillon 		while ((elm = strsep(&ptr, ",")) != NULL) {
276*69f5a58cSMatthew Dillon 			if (strcmp(av[0], elm) == 0)
277*69f5a58cSMatthew Dillon 				break;
278*69f5a58cSMatthew Dillon 		}
279*69f5a58cSMatthew Dillon 		if (elm == NULL) {
280*69f5a58cSMatthew Dillon 			fprintf(stderr, "hammer-remote: request does not match "
281*69f5a58cSMatthew Dillon 					"restricted command\n");
282*69f5a58cSMatthew Dillon 			exit(1);
283*69f5a58cSMatthew Dillon 		}
284*69f5a58cSMatthew Dillon 		free(ptr);
285*69f5a58cSMatthew Dillon 	}
286*69f5a58cSMatthew Dillon 
287*69f5a58cSMatthew Dillon 	/*
288*69f5a58cSMatthew Dillon 	 * Parse commands
289*69f5a58cSMatthew Dillon 	 */
290367431cfSMatthew Dillon 	if (strcmp(av[0], "synctid") == 0) {
291367431cfSMatthew Dillon 		hammer_cmd_synctid(av + 1, ac - 1);
292367431cfSMatthew Dillon 		exit(0);
293367431cfSMatthew Dillon 	}
2945e435c92SMatthew Dillon 	if (strcmp(av[0], "namekey2") == 0) {
2955e435c92SMatthew Dillon 		int64_t key;
2965e435c92SMatthew Dillon 		int32_t crcx;
2975e435c92SMatthew Dillon 		int len;
2985e435c92SMatthew Dillon 		const char *aname = av[1];
2995e435c92SMatthew Dillon 
3005e435c92SMatthew Dillon 		if (aname == NULL)
3015e435c92SMatthew Dillon 			usage(1);
3025e435c92SMatthew Dillon 		len = strlen(aname);
3035e435c92SMatthew Dillon 		key = (u_int32_t)crc32(aname, len) & 0xFFFFFFFEU;
3045e435c92SMatthew Dillon 
3055e435c92SMatthew Dillon 		switch(len) {
3065e435c92SMatthew Dillon 		default:
3075e435c92SMatthew Dillon 			crcx = crc32(aname + 3, len - 5);
3085e435c92SMatthew Dillon 			crcx = crcx ^ (crcx >> 6) ^ (crcx >> 12);
3095e435c92SMatthew Dillon 			key |= (int64_t)(crcx & 0x3F) << 42;
3105e435c92SMatthew Dillon 			/* fall through */
3115e435c92SMatthew Dillon 		case 5:
3125e435c92SMatthew Dillon 		case 4:
3135e435c92SMatthew Dillon 			/* fall through */
3145e435c92SMatthew Dillon 		case 3:
3155e435c92SMatthew Dillon 			key |= ((int64_t)(aname[2] & 0x1F) << 48);
3165e435c92SMatthew Dillon 			/* fall through */
3175e435c92SMatthew Dillon 		case 2:
3185e435c92SMatthew Dillon 			key |= ((int64_t)(aname[1] & 0x1F) << 53) |
3195e435c92SMatthew Dillon 			       ((int64_t)(aname[len-2] & 0x1F) << 37);
3205e435c92SMatthew Dillon 			/* fall through */
3215e435c92SMatthew Dillon 		case 1:
3225e435c92SMatthew Dillon 			key |= ((int64_t)(aname[0] & 0x1F) << 58) |
3235e435c92SMatthew Dillon 			       ((int64_t)(aname[len-1] & 0x1F) << 32);
3245e435c92SMatthew Dillon 			/* fall through */
3255e435c92SMatthew Dillon 		case 0:
3265e435c92SMatthew Dillon 			break;
3275e435c92SMatthew Dillon 		}
3285e435c92SMatthew Dillon 		if (key == 0)
3295e435c92SMatthew Dillon 			key |= 0x100000000LL;
330a276dc6bSMatthew Dillon 		printf("0x%016jx\n", (uintmax_t)key);
3315e435c92SMatthew Dillon 		exit(0);
3325e435c92SMatthew Dillon 	}
3335e435c92SMatthew Dillon 	if (strcmp(av[0], "namekey1") == 0) {
334cbd800c2SMatthew Dillon 		int64_t key;
335cbd800c2SMatthew Dillon 
336cbd800c2SMatthew Dillon 		if (av[1] == NULL)
337cbd800c2SMatthew Dillon 			usage(1);
338cbd800c2SMatthew Dillon 		key = (int64_t)(crc32(av[1], strlen(av[1])) & 0x7FFFFFFF) << 32;
339cbd800c2SMatthew Dillon 		if (key == 0)
340cbd800c2SMatthew Dillon 			key |= 0x100000000LL;
341a276dc6bSMatthew Dillon 		printf("0x%016jx\n", (uintmax_t)key);
342cbd800c2SMatthew Dillon 		exit(0);
343cbd800c2SMatthew Dillon 	}
344cbd800c2SMatthew Dillon 	if (strcmp(av[0], "namekey32") == 0) {
345cbd800c2SMatthew Dillon 		int32_t key;
346cbd800c2SMatthew Dillon 
347cbd800c2SMatthew Dillon 		if (av[1] == NULL)
348cbd800c2SMatthew Dillon 			usage(1);
349cbd800c2SMatthew Dillon 		key = crc32(av[1], strlen(av[1])) & 0x7FFFFFFF;
350cbd800c2SMatthew Dillon 		if (key == 0)
351cbd800c2SMatthew Dillon 			++key;
352cbd800c2SMatthew Dillon 		printf("0x%08x\n", key);
353cbd800c2SMatthew Dillon 		exit(0);
354cbd800c2SMatthew Dillon 	}
35534ebae70SMatthew Dillon 	if (strcmp(av[0], "pfs-status") == 0) {
35634ebae70SMatthew Dillon 		hammer_cmd_pseudofs_status(av + 1, ac - 1);
35734ebae70SMatthew Dillon 		exit(0);
35834ebae70SMatthew Dillon 	}
359d4e5b69bSMatthew Dillon 	if (strcmp(av[0], "pfs-master") == 0) {
360d4e5b69bSMatthew Dillon 		hammer_cmd_pseudofs_create(av + 1, ac - 1, 0);
361d4e5b69bSMatthew Dillon 		exit(0);
362d4e5b69bSMatthew Dillon 	}
363d4e5b69bSMatthew Dillon 	if (strcmp(av[0], "pfs-slave") == 0) {
364d4e5b69bSMatthew Dillon 		hammer_cmd_pseudofs_create(av + 1, ac - 1, 1);
36534ebae70SMatthew Dillon 		exit(0);
36634ebae70SMatthew Dillon 	}
36734ebae70SMatthew Dillon 	if (strcmp(av[0], "pfs-update") == 0) {
368d4e5b69bSMatthew Dillon 		hammer_cmd_pseudofs_update(av + 1, ac - 1);
36966db8054SMatthew Dillon 		exit(0);
37066db8054SMatthew Dillon 	}
3719c67b4d2SMatthew Dillon 	if (strcmp(av[0], "pfs-upgrade") == 0) {
3729c67b4d2SMatthew Dillon 		hammer_cmd_pseudofs_upgrade(av + 1, ac - 1);
3739c67b4d2SMatthew Dillon 		exit(0);
3749c67b4d2SMatthew Dillon 	}
3759c67b4d2SMatthew Dillon 	if (strcmp(av[0], "pfs-downgrade") == 0) {
3769c67b4d2SMatthew Dillon 		hammer_cmd_pseudofs_downgrade(av + 1, ac - 1);
3779c67b4d2SMatthew Dillon 		exit(0);
3789c67b4d2SMatthew Dillon 	}
379243ca327SMatthew Dillon 	if (strcmp(av[0], "pfs-destroy") == 0) {
380243ca327SMatthew Dillon 		hammer_cmd_pseudofs_destroy(av + 1, ac - 1);
381243ca327SMatthew Dillon 		exit(0);
382243ca327SMatthew Dillon 	}
383a7fbbf91SMatthew Dillon 	if (strcmp(av[0], "status") == 0) {
384a7fbbf91SMatthew Dillon 		hammer_cmd_status(av + 1, ac - 1);
385a7fbbf91SMatthew Dillon 		exit(0);
386a7fbbf91SMatthew Dillon 	}
38713ce745dSMatthew Dillon 	if (strcmp(av[0], "prune") == 0) {
388b5aaba7fSMatthew Dillon 		hammer_cmd_softprune(av + 1, ac - 1, 0);
38913ce745dSMatthew Dillon 		exit(0);
39013ce745dSMatthew Dillon 	}
39183f2a3aaSMatthew Dillon 	if (strcmp(av[0], "config") == 0) {
39283f2a3aaSMatthew Dillon 		hammer_cmd_config(av + 1, ac - 1);
39383f2a3aaSMatthew Dillon 		exit(0);
39483f2a3aaSMatthew Dillon 	}
39583f2a3aaSMatthew Dillon 	if (strcmp(av[0], "viconfig") == 0) {
39683f2a3aaSMatthew Dillon 		hammer_cmd_viconfig(av + 1, ac - 1);
39783f2a3aaSMatthew Dillon 		exit(0);
39883f2a3aaSMatthew Dillon 	}
3996a6e350fSMatthew Dillon 	if (strcmp(av[0], "cleanup") == 0) {
4006a6e350fSMatthew Dillon 		hammer_cmd_cleanup(av + 1, ac - 1);
4016a6e350fSMatthew Dillon 		exit(0);
4026a6e350fSMatthew Dillon 	}
403b66b9421SAntonio Huete 	if (strcmp(av[0], "info") == 0) {
404eac446c5SMatthew Dillon 		hammer_cmd_info();
405b66b9421SAntonio Huete 		exit(0);
406b66b9421SAntonio Huete 	}
407b5aaba7fSMatthew Dillon 	if (strcmp(av[0], "prune-everything") == 0) {
408b5aaba7fSMatthew Dillon 		hammer_cmd_softprune(av + 1, ac - 1, 1);
409e8969ef0SMatthew Dillon 		exit(0);
410e8969ef0SMatthew Dillon 	}
411*69f5a58cSMatthew Dillon 	if (strcmp(av[0], "ssh-remote") == 0) {
412*69f5a58cSMatthew Dillon 		if (ac != 3)
413*69f5a58cSMatthew Dillon 			usage(1);
414*69f5a58cSMatthew Dillon 		hammer_cmd_sshremote(av[1], av[2]);
415*69f5a58cSMatthew Dillon 		exit(0);
416*69f5a58cSMatthew Dillon 	}
41783f2a3aaSMatthew Dillon 	if (strcmp(av[0], "snap") == 0) {
41883f2a3aaSMatthew Dillon 		hammer_cmd_snap(av + 1, ac - 1, 0, 1);
41983f2a3aaSMatthew Dillon 		exit(0);
42083f2a3aaSMatthew Dillon 	}
42183f2a3aaSMatthew Dillon 	if (strcmp(av[0], "snaplo") == 0) {
42283f2a3aaSMatthew Dillon 		hammer_cmd_snap(av + 1, ac - 1, 0, 0);
42383f2a3aaSMatthew Dillon 		exit(0);
42483f2a3aaSMatthew Dillon 	}
42583f2a3aaSMatthew Dillon 	if (strcmp(av[0], "snapq") == 0) {
42683f2a3aaSMatthew Dillon 		hammer_cmd_snap(av + 1, ac - 1, 1, 0);
42783f2a3aaSMatthew Dillon 		exit(0);
42883f2a3aaSMatthew Dillon 	}
42983f2a3aaSMatthew Dillon 	if (strcmp(av[0], "snapls") == 0) {
43083f2a3aaSMatthew Dillon 		hammer_cmd_snapls(av + 1, ac - 1);
43183f2a3aaSMatthew Dillon 		exit(0);
43283f2a3aaSMatthew Dillon 	}
43383f2a3aaSMatthew Dillon 	if (strcmp(av[0], "snaprm") == 0) {
43483f2a3aaSMatthew Dillon 		hammer_cmd_snaprm(av + 1, ac - 1);
43583f2a3aaSMatthew Dillon 		exit(0);
43683f2a3aaSMatthew Dillon 	}
4376b669ab4SMichael Neumann 	if (strcmp(av[0], "snapshot") == 0) {
4386b669ab4SMichael Neumann 		hammer_cmd_snapshot(av + 1, ac - 1);
4396b669ab4SMichael Neumann 		exit(0);
4406b669ab4SMichael Neumann 	}
44168e079b8SMatthew Dillon 	if (strcmp(av[0], "bstats") == 0) {
44268e079b8SMatthew Dillon 		hammer_cmd_bstats(av + 1, ac - 1);
44368e079b8SMatthew Dillon 		exit(0);
44468e079b8SMatthew Dillon 	}
44568e079b8SMatthew Dillon 	if (strcmp(av[0], "iostats") == 0) {
44668e079b8SMatthew Dillon 		hammer_cmd_iostats(av + 1, ac - 1);
44768e079b8SMatthew Dillon 		exit(0);
44868e079b8SMatthew Dillon 	}
44913ce745dSMatthew Dillon 
45013ce745dSMatthew Dillon 	if (strncmp(av[0], "history", 7) == 0) {
45113ce745dSMatthew Dillon 		hammer_cmd_history(av[0] + 7, av + 1, ac - 1);
45213ce745dSMatthew Dillon 		exit(0);
45313ce745dSMatthew Dillon 	}
454797a0b63SMatthew Dillon 	if (strcmp(av[0], "rebalance") == 0) {
455797a0b63SMatthew Dillon 		signal(SIGINT, sigalrm);
456797a0b63SMatthew Dillon 		hammer_cmd_rebalance(av + 1, ac - 1);
457797a0b63SMatthew Dillon 		exit(0);
458797a0b63SMatthew Dillon 	}
459ba7b52c9SMatthew Dillon 	if (strncmp(av[0], "reblock", 7) == 0) {
4606a6e350fSMatthew Dillon 		signal(SIGINT, sigalrm);
461ba7b52c9SMatthew Dillon 		if (strcmp(av[0], "reblock") == 0)
462ba7b52c9SMatthew Dillon 			hammer_cmd_reblock(av + 1, ac - 1, -1);
463ba7b52c9SMatthew Dillon 		else if (strcmp(av[0], "reblock-btree") == 0)
464ba7b52c9SMatthew Dillon 			hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_BTREE);
46558c17893SMatthew Dillon 		else if (strcmp(av[0], "reblock-inodes") == 0)
46658c17893SMatthew Dillon 			hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_INODES);
4679e29c876SMatthew Dillon 		else if (strcmp(av[0], "reblock-dirs") == 0)
4689e29c876SMatthew Dillon 			hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DIRS);
469ba7b52c9SMatthew Dillon 		else if (strcmp(av[0], "reblock-data") == 0)
470ba7b52c9SMatthew Dillon 			hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DATA);
471ba7b52c9SMatthew Dillon 		else
472ba7b52c9SMatthew Dillon 			usage(1);
4733f673d5cSMatthew Dillon 		exit(0);
4743f673d5cSMatthew Dillon 	}
475a7fbbf91SMatthew Dillon 	if (strncmp(av[0], "mirror", 6) == 0) {
476a7fbbf91SMatthew Dillon 		if (strcmp(av[0], "mirror-read") == 0)
47748eadef9SMatthew Dillon 			hammer_cmd_mirror_read(av + 1, ac - 1, 0);
4787a27dae7SMatthew Dillon 		else if (strcmp(av[0], "mirror-read-stream") == 0)
47948eadef9SMatthew Dillon 			hammer_cmd_mirror_read(av + 1, ac - 1, 1);
480a7fbbf91SMatthew Dillon 		else if (strcmp(av[0], "mirror-write") == 0)
481a7fbbf91SMatthew Dillon 			hammer_cmd_mirror_write(av + 1, ac - 1);
482a7fbbf91SMatthew Dillon 		else if (strcmp(av[0], "mirror-copy") == 0)
48348eadef9SMatthew Dillon 			hammer_cmd_mirror_copy(av + 1, ac - 1, 0);
48448eadef9SMatthew Dillon 		else if (strcmp(av[0], "mirror-stream") == 0)
48548eadef9SMatthew Dillon 			hammer_cmd_mirror_copy(av + 1, ac - 1, 1);
486243ca327SMatthew Dillon 		else if (strcmp(av[0], "mirror-dump") == 0)
487243ca327SMatthew Dillon 			hammer_cmd_mirror_dump();
488a7fbbf91SMatthew Dillon 		else
489a7fbbf91SMatthew Dillon 			usage(1);
490a7fbbf91SMatthew Dillon 		exit(0);
491a7fbbf91SMatthew Dillon 	}
492bb29b5d8SMatthew Dillon 	if (strcmp(av[0], "dedup-simulate") == 0) {
493bb29b5d8SMatthew Dillon 		hammer_cmd_dedup_simulate(av + 1, ac - 1);
494bb29b5d8SMatthew Dillon 		exit(0);
495bb29b5d8SMatthew Dillon 	}
496bb29b5d8SMatthew Dillon 	if (strcmp(av[0], "dedup") == 0) {
497bb29b5d8SMatthew Dillon 		hammer_cmd_dedup(av + 1, ac - 1);
498bb29b5d8SMatthew Dillon 		exit(0);
499bb29b5d8SMatthew Dillon 	}
500de1c0b31SMatthew Dillon 	if (strcmp(av[0], "version") == 0) {
501de1c0b31SMatthew Dillon 		hammer_cmd_get_version(av + 1, ac - 1);
502de1c0b31SMatthew Dillon 		exit(0);
503de1c0b31SMatthew Dillon 	}
504de1c0b31SMatthew Dillon 	if (strcmp(av[0], "version-upgrade") == 0) {
505de1c0b31SMatthew Dillon 		hammer_cmd_set_version(av + 1, ac - 1);
506de1c0b31SMatthew Dillon 		exit(0);
507de1c0b31SMatthew Dillon 	}
508d121f61cSMichael Neumann 	if (strcmp(av[0], "volume-add") == 0) {
509d121f61cSMichael Neumann 		hammer_cmd_volume_add(av + 1, ac - 1);
510e27700cfSMichael Neumann 		exit(0);
511e27700cfSMichael Neumann 	}
512865c9609SMichael Neumann 	if (strcmp(av[0], "volume-del") == 0) {
513865c9609SMichael Neumann 		hammer_cmd_volume_del(av + 1, ac - 1);
514865c9609SMichael Neumann 		exit(0);
515865c9609SMichael Neumann 	}
516e914c91dSStathis Kamperis 	if (strcmp(av[0], "volume-list") == 0) {
517e914c91dSStathis Kamperis 		hammer_cmd_volume_list(av + 1, ac - 1);
518e914c91dSStathis Kamperis 		exit(0);
519e914c91dSStathis Kamperis 	}
52061aeeb33SMatthew Dillon 
52161aeeb33SMatthew Dillon 	uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status);
52261aeeb33SMatthew Dillon 	if (status != uuid_s_ok) {
52361aeeb33SMatthew Dillon 		errx(1, "uuids file does not have the DragonFly "
52461aeeb33SMatthew Dillon 			"HAMMER filesystem type");
52561aeeb33SMatthew Dillon 	}
526d38ab092SMatthew Dillon 
527d38ab092SMatthew Dillon 	if (strcmp(av[0], "show") == 0) {
528e7f926a5SMatthew Dillon 		u_int32_t lo = 0;
529a276dc6bSMatthew Dillon 		intmax_t obj_id = (int64_t)HAMMER_MIN_OBJID;
53061aeeb33SMatthew Dillon 
531d38ab092SMatthew Dillon 		hammer_parsedevs(blkdevs);
532d38ab092SMatthew Dillon 		if (ac > 1)
533a276dc6bSMatthew Dillon 			sscanf(av[1], "%08x:%jx", &lo, &obj_id);
534a276dc6bSMatthew Dillon 		hammer_cmd_show(-1, lo, (int64_t)obj_id, 0, NULL, NULL);
535d38ab092SMatthew Dillon 		exit(0);
536d38ab092SMatthew Dillon 	}
5376aec797fSMatthew Dillon 	if (strcmp(av[0], "show-undo") == 0) {
5386aec797fSMatthew Dillon 		hammer_parsedevs(blkdevs);
5396aec797fSMatthew Dillon 		hammer_cmd_show_undo();
5406aec797fSMatthew Dillon 		exit(0);
5416aec797fSMatthew Dillon 	}
542b9107f58SMatthew Dillon 	if (strcmp(av[0], "recover") == 0) {
543b9107f58SMatthew Dillon 		hammer_parsedevs(blkdevs);
544b9107f58SMatthew Dillon 		if (ac <= 1)
545b9107f58SMatthew Dillon 			errx(1, "hammer recover required target directory");
546b9107f58SMatthew Dillon 		hammer_cmd_recover(av[1]);
547b9107f58SMatthew Dillon 		exit(0);
548b9107f58SMatthew Dillon 	}
549eb3f8f1fSMatthew Dillon 	if (strcmp(av[0], "blockmap") == 0) {
550eb3f8f1fSMatthew Dillon 		hammer_parsedevs(blkdevs);
551eb3f8f1fSMatthew Dillon 		hammer_cmd_blockmap();
552eb3f8f1fSMatthew Dillon 		exit(0);
553eb3f8f1fSMatthew Dillon 	}
5546ed4c886SMatthew Dillon 	if (strcmp(av[0], "checkmap") == 0) {
5556ed4c886SMatthew Dillon 		hammer_parsedevs(blkdevs);
5566ed4c886SMatthew Dillon 		hammer_cmd_checkmap();
5576ed4c886SMatthew Dillon 		exit(0);
5586ed4c886SMatthew Dillon 	}
5590dfeb6c8SMatthew Dillon 	usage(1);
5600dfeb6c8SMatthew Dillon 	/* not reached */
5610dfeb6c8SMatthew Dillon 	return(0);
5620dfeb6c8SMatthew Dillon }
5630dfeb6c8SMatthew Dillon 
5649c9ac2f1SMatthew Dillon /*
5659c9ac2f1SMatthew Dillon  * Parse the device specification.
5669c9ac2f1SMatthew Dillon  *
5679c9ac2f1SMatthew Dillon  * Multi-volume hammer devices are colon-separated.  Each element
5689c9ac2f1SMatthew Dillon  * may be further expanded via /etc/devtab.  One may also specify
5699c9ac2f1SMatthew Dillon  * a single element which is expanded into multiple elements via
5709c9ac2f1SMatthew Dillon  * /etc/devtab.
5719c9ac2f1SMatthew Dillon  */
5720dfeb6c8SMatthew Dillon static
5730dfeb6c8SMatthew Dillon void
574d38ab092SMatthew Dillon hammer_parsedevs(const char *blkdevs)
575d38ab092SMatthew Dillon {
576d38ab092SMatthew Dillon 	char *copy;
577d38ab092SMatthew Dillon 	char *volname;
578d38ab092SMatthew Dillon 
579d38ab092SMatthew Dillon 	if (blkdevs == NULL) {
580f6532f03SThomas Nikolajsen 		errx(1, "A -f blkdevs specification is required "
581d38ab092SMatthew Dillon 			"for this command");
582d38ab092SMatthew Dillon 	}
583d38ab092SMatthew Dillon 
584d38ab092SMatthew Dillon 	copy = strdup(blkdevs);
585d38ab092SMatthew Dillon 	while ((volname = copy) != NULL) {
586d38ab092SMatthew Dillon 		if ((copy = strchr(copy, ':')) != NULL)
587d38ab092SMatthew Dillon 			*copy++ = 0;
5889c9ac2f1SMatthew Dillon 		volname = getdevpath(volname, 0);
5899c9ac2f1SMatthew Dillon 		if (strchr(volname, ':'))
5909c9ac2f1SMatthew Dillon 			hammer_parsedevs(volname);
5919c9ac2f1SMatthew Dillon 		else
592d38ab092SMatthew Dillon 			setup_volume(-1, volname, 0, O_RDONLY);
593d38ab092SMatthew Dillon 	}
594d38ab092SMatthew Dillon }
595d38ab092SMatthew Dillon 
596d38ab092SMatthew Dillon static
597d38ab092SMatthew Dillon void
5980006adaeSMatthew Dillon sigalrm(int signo __unused)
5990006adaeSMatthew Dillon {
6000006adaeSMatthew Dillon 	/* do nothing (interrupts HAMMER ioctl) */
6010006adaeSMatthew Dillon }
6020006adaeSMatthew Dillon 
6030006adaeSMatthew Dillon static
6040006adaeSMatthew Dillon void
605445faa69SMatthew Dillon sigintr(int signo __unused)
606445faa69SMatthew Dillon {
607445faa69SMatthew Dillon 	if (RunningIoctl == 0)
608445faa69SMatthew Dillon 		_exit(1);
609445faa69SMatthew Dillon 	DidInterrupt = 1;
610445faa69SMatthew Dillon 	/* do nothing (interrupts HAMMER ioctl) */
611445faa69SMatthew Dillon }
612445faa69SMatthew Dillon 
613445faa69SMatthew Dillon static
614445faa69SMatthew Dillon void
6150dfeb6c8SMatthew Dillon usage(int exit_code)
6160dfeb6c8SMatthew Dillon {
6170dfeb6c8SMatthew Dillon 	fprintf(stderr,
6180dfeb6c8SMatthew Dillon 		"hammer -h\n"
6198ceaba31SSascha Wildner 		"hammer [-2BqrvXy] [-b bandwidth] [-C cachesize[:readahead]] [-c cyclefile]\n"
6203d7b2393SMatthew Dillon 		"       [-f blkdevs] [-i delay] [-t seconds] [-S splitup]\n"
6213d7b2393SMatthew Dillon 		"	command [argument ...]\n"
62284082922SThomas Nikolajsen 		"hammer synctid <filesystem> [quick]\n"
62384082922SThomas Nikolajsen 		"hammer bstats [interval]\n"
62484082922SThomas Nikolajsen 		"hammer iostats [interval]\n"
625bb8e52c0SThomas Nikolajsen 		"hammer history[@offset[,len]] <file> ...\n"
6265e435c92SMatthew Dillon 		"hammer namekey1 <path>\n"
6275e435c92SMatthew Dillon 		"hammer namekey2 <path>\n"
6284567021bSThomas Nikolajsen 		"hammer namekey32 <path>\n"
629bb8e52c0SThomas Nikolajsen 		"hammer cleanup [<filesystem> ...]\n"
630b66b9421SAntonio Huete 		"hammer info\n"
631bb8e52c0SThomas Nikolajsen 		"hammer snapshot [<filesystem>] <snapshot-dir>\n"
63216265794SThomas Nikolajsen 		"hammer snapshot <filesystem> <snapshot-dir> [<note>]\n"
633bb8e52c0SThomas Nikolajsen 		"hammer prune <softlink-dir>\n"
634bb8e52c0SThomas Nikolajsen 		"hammer prune-everything <filesystem>\n"
635797a0b63SMatthew Dillon 		"hammer rebalance <filesystem> [saturation_percentage]\n"
6364567021bSThomas Nikolajsen 		"hammer reblock[-btree|-inodes|-dirs|-data] "
63784082922SThomas Nikolajsen 			"<filesystem> [fill_percentage]\n"
63834bb69d8SThomas Nikolajsen 		"hammer pfs-status <dirpath> ...\n"
639d4e5b69bSMatthew Dillon 		"hammer pfs-master <dirpath> [options]\n"
640d4e5b69bSMatthew Dillon 		"hammer pfs-slave <dirpath> [options]\n"
64134ebae70SMatthew Dillon 		"hammer pfs-update <dirpath> [options]\n"
6429c67b4d2SMatthew Dillon 		"hammer pfs-upgrade <dirpath>\n"
6439c67b4d2SMatthew Dillon 		"hammer pfs-downgrade <dirpath>\n"
6449c67b4d2SMatthew Dillon 		"hammer pfs-destroy <dirpath>\n"
645bb8e52c0SThomas Nikolajsen 		"hammer mirror-read <filesystem> [begin-tid]\n"
646bb8e52c0SThomas Nikolajsen 		"hammer mirror-read-stream <filesystem> [begin-tid]\n"
647bb8e52c0SThomas Nikolajsen 		"hammer mirror-write <filesystem>\n"
648bb8e52c0SThomas Nikolajsen 		"hammer mirror-dump\n"
649bb8e52c0SThomas Nikolajsen 		"hammer mirror-copy [[user@]host:]<filesystem>"
650bb8e52c0SThomas Nikolajsen 				  " [[user@]host:]<filesystem>\n"
651bb8e52c0SThomas Nikolajsen 		"hammer mirror-stream [[user@]host:]<filesystem>"
652bb8e52c0SThomas Nikolajsen 				    " [[user@]host:]<filesystem>\n"
653*69f5a58cSMatthew Dillon 		"hammer ssh-remote command filesystem\n"
6545e435c92SMatthew Dillon 		"hammer version <filesystem>\n"
6554567021bSThomas Nikolajsen 		"hammer version-upgrade <filesystem> <version> [force]\n"
656d121f61cSMichael Neumann 		"hammer volume-add <device> <filesystem>\n"
657865c9609SMichael Neumann 		"hammer volume-del <device> <filesystem>\n"
658e914c91dSStathis Kamperis 		"hammer volume-list <filesystem>\n"
6590dfeb6c8SMatthew Dillon 	);
66083f2a3aaSMatthew Dillon 
661f6532f03SThomas Nikolajsen 	fprintf(stderr, "\nHAMMER utility version 3+ commands:\n");
66283f2a3aaSMatthew Dillon 
66383f2a3aaSMatthew Dillon 	fprintf(stderr,
66483f2a3aaSMatthew Dillon 		"hammer config [<filesystem> [<configfile>]]\n"
66583f2a3aaSMatthew Dillon 		"hammer viconfig [<filesystem>]\n"
666f6532f03SThomas Nikolajsen 		"hammer snap <path> [<note>]\n"
667f6532f03SThomas Nikolajsen 		"hammer snaplo <path> [<note>]\n"
668f6532f03SThomas Nikolajsen 		"hammer snapq <dir> [<note>]\n"
669aaf93065SThomas Nikolajsen 		"hammer snaprm <path> ...\n"
670aaf93065SThomas Nikolajsen 		"hammer snaprm <transid> ...\n"
671aaf93065SThomas Nikolajsen 		"hammer snaprm <filesystem> <transid> ...\n"
672f6532f03SThomas Nikolajsen 		"hammer snapls [<path> ...]\n"
673f6532f03SThomas Nikolajsen 	);
674f6532f03SThomas Nikolajsen 
675f6532f03SThomas Nikolajsen 	fprintf(stderr, "\nHAMMER utility version 4+ commands:\n");
676f6532f03SThomas Nikolajsen 
677f6532f03SThomas Nikolajsen 	fprintf(stderr,
678c71cab34SMatthew Dillon 		"hammer -f blkdevs blockmap\n"
679c71cab34SMatthew Dillon 		"hammer -f blkdevs checkmap\n"
680c71cab34SMatthew Dillon 		"hammer -f blkdevs [-qqq] show [lo:objid]\n"
681f6532f03SThomas Nikolajsen 		"hammer -f blkdevs show-undo\n"
682b9107f58SMatthew Dillon 		"hammer -f blkdevs recover <target_dir>\n"
68383f2a3aaSMatthew Dillon 	);
68483f2a3aaSMatthew Dillon 
685bb29b5d8SMatthew Dillon 	fprintf(stderr, "\nHAMMER utility version 5+ commands:\n");
686bb29b5d8SMatthew Dillon 
687bb29b5d8SMatthew Dillon 	fprintf(stderr,
688bb29b5d8SMatthew Dillon 		"hammer dedup-simulate <filesystem>\n"
689bb29b5d8SMatthew Dillon 		"hammer dedup <filesystem>\n"
690bb29b5d8SMatthew Dillon 	);
691bb29b5d8SMatthew Dillon 
6920dfeb6c8SMatthew Dillon 	exit(exit_code);
6930dfeb6c8SMatthew Dillon }
694d38ab092SMatthew Dillon 
695