2 * Copyright (c) 2007 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * $DragonFly: src/sbin/hammer/hammer.c,v 1.14 2008/05/04 19:18:17 dillon Exp $
41 static void hammer_parsetime(u_int64_t
*tidp
, const char *timestr
);
42 static void hammer_waitsync(int dosleep
);
43 static void hammer_parsedevs(const char *blkdevs
);
44 static void sigalrm(int signo
);
45 static void usage(int exit_code
);
53 main(int ac
, char **av
)
62 while ((ch
= getopt(ac
, av
, "hf:rs:t:vx")) != -1) {
77 timeout
= strtol(optarg
, NULL
, 0);
98 signal(SIGALRM
, sigalrm
);
102 if (strcmp(av
[0], "now") == 0) {
104 tid
= (hammer_tid_t
)time(NULL
) * 1000000000LLU;
105 printf("0x%08x\n", (int)(tid
/ 1000000000LL));
108 if (strcmp(av
[0], "now64") == 0) {
110 gettimeofday(&tv
, NULL
);
111 tid
= (hammer_tid_t
)tv
.tv_sec
* 1000000000LLU +
112 tv
.tv_usec
* 1000LLU;
113 printf("0x%016llx\n", tid
);
116 if (strcmp(av
[0], "stamp") == 0) {
119 hammer_parsetime(&tid
, av
[1]);
120 printf("0x%08x\n", (int)(tid
/ 1000000000LL));
123 if (strcmp(av
[0], "stamp64") == 0) {
126 hammer_parsetime(&tid
, av
[1]);
127 printf("0x%016llx\n", tid
);
130 if (strcmp(av
[0], "namekey") == 0) {
135 key
= (int64_t)(crc32(av
[1], strlen(av
[1])) & 0x7FFFFFFF) << 32;
137 key
|= 0x100000000LL
;
138 printf("0x%016llx\n", key
);
141 if (strcmp(av
[0], "namekey32") == 0) {
146 key
= crc32(av
[1], strlen(av
[1])) & 0x7FFFFFFF;
149 printf("0x%08x\n", key
);
152 if (strcmp(av
[0], "prune") == 0) {
153 hammer_cmd_prune(av
+ 1, ac
- 1);
157 if (strncmp(av
[0], "history", 7) == 0) {
158 hammer_cmd_history(av
[0] + 7, av
+ 1, ac
- 1);
161 if (strcmp(av
[0], "reblock") == 0) {
162 hammer_cmd_reblock(av
+ 1, ac
- 1);
166 uuid_name_lookup(&Hammer_FSType
, "DragonFly HAMMER", &status
);
167 if (status
!= uuid_s_ok
) {
168 errx(1, "uuids file does not have the DragonFly "
169 "HAMMER filesystem type");
172 if (strcmp(av
[0], "show") == 0) {
173 hammer_off_t node_offset
= (hammer_off_t
)-1;
175 hammer_parsedevs(blkdevs
);
177 sscanf(av
[1], "%llx", &node_offset
);
178 hammer_cmd_show(node_offset
, 0, NULL
, NULL
);
181 if (strcmp(av
[0], "blockmap") == 0) {
182 hammer_parsedevs(blkdevs
);
183 hammer_cmd_blockmap();
192 * Parse a timestamp for the mount point
199 hammer_parsetime(u_int64_t
*tidp
, const char *timestr
)
206 gettimeofday(&tv
, NULL
);
211 if (isalpha(timestr
[strlen(timestr
)-1])) {
212 if (sscanf(timestr
, "%d%c", &n
, &c
) != 2)
240 localtime_r(&tv
.tv_sec
, &tm
);
241 seconds
= (double)tm
.tm_sec
;
244 n
= sscanf(timestr
, "%4d%2d%2d:%2d%2d%lf",
245 &tm
.tm_year
, &tm
.tm_mon
, &tm
.tm_mday
,
246 &tm
.tm_hour
, &tm
.tm_min
, &seconds
);
249 /* if [:hhmmss] is omitted, assume :000000.0 */
251 tm
.tm_hour
= tm
.tm_min
= tm
.tm_sec
= 0;
253 tm
.tm_sec
= (int)seconds
;
254 tv
.tv_sec
= mktime(&tm
);
255 tv
.tv_usec
= (int)((seconds
- floor(seconds
)) * 1000000.0);
257 *tidp
= (u_int64_t
)tv
.tv_sec
* 1000000000LLU +
258 tv
.tv_usec
* 1000LLU;
262 * If the TID is within 60 seconds of the current time we sync(). If
263 * dosleep is non-zero and the TID is within 1 second of the current time
264 * we wait for the second-hand to turn over.
266 * The NoSyncOpt prevents both the sync() call and any sleeps from occuring.
270 hammer_waitsync(int dosleep
)
274 if (NoSyncOpt
== 0) {
276 t1
= t2
= time(NULL
);
277 while (dosleep
&& t1
== t2
) {
286 hammer_parsedevs(const char *blkdevs
)
291 if (blkdevs
== NULL
) {
292 errx(1, "A -f blkdevs specification is required "
296 copy
= strdup(blkdevs
);
297 while ((volname
= copy
) != NULL
) {
298 if ((copy
= strchr(copy
, ':')) != NULL
)
300 setup_volume(-1, volname
, 0, O_RDONLY
);
306 sigalrm(int signo __unused
)
308 /* do nothing (interrupts HAMMER ioctl) */
317 "hammer [-x] now[64]\n"
318 "hammer stamp[64] <time>\n"
319 "hammer [-s linkpath] prune <filesystem> [using <configfile>]\n"
320 "hammer [-s linkpath] prune <filesystem> from <modulo_time> to "
321 "<modulo_time> every <modulo_time>\n"
322 "hammer prune <filesystem> everything\n"
323 "hammer reblock <filesystem> [compact%%] (default 90%%)\n"
324 "hammer history[@offset[,len]] <file-1>...<file-N>\n"
325 "hammer -f blkdevs [-r] show\n"
326 "hammer -f blkdevs blockmap\n"
328 fprintf(stderr
, "time: +n[s/m/h/D/M/Y]\n"
329 "time: yyyymmdd[:hhmmss]\n"
330 "modulo_time: n{s,m,h,d,M,y}\n");