1 /* 2 * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 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 16 * distribution. 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. 20 * 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 32 * SUCH DAMAGE. 33 */ 34 35 #include "hammer.h" 36 37 static void hammer_parsedevs(const char *blkdevs); 38 static void sigalrm(int signo); 39 static void sigintr(int signo); 40 static void usage(int exit_code); 41 42 int RecurseOpt; 43 int VerboseOpt; 44 int QuietOpt; 45 int NoSyncOpt; 46 int TwoWayPipeOpt; 47 int TimeoutOpt; 48 int DelayOpt = 5; 49 char *SshPort; 50 int ForceYesOpt = 0; 51 int CompressOpt; 52 int ForceOpt; 53 int RunningIoctl; 54 int DidInterrupt; 55 int BulkOpt; 56 int AllPFS; 57 uint64_t BandwidthOpt; 58 uint64_t SplitupOpt = 4ULL * 1024ULL * 1024ULL * 1024ULL; 59 uint64_t MemoryLimit = 1024LLU * 1024 * 1024; 60 const char *SplitupOptStr; 61 const char *CyclePath; 62 const char *RestrictTarget; 63 64 int 65 main(int ac, char **av) 66 { 67 char *blkdevs = NULL; 68 char *ptr; 69 char *restrictcmd = NULL; 70 uint32_t status; 71 int ch; 72 int cacheSize = 0; 73 74 while ((ch = getopt(ac, av, 75 "b:c:de:hf:i:m:p:qrt:v2yABC:FR:S:T:X")) != -1) { 76 switch(ch) { 77 case '2': 78 TwoWayPipeOpt = 1; 79 break; 80 case 'y': 81 ForceYesOpt = 1; 82 break; 83 case 'b': 84 BandwidthOpt = strtoull(optarg, &ptr, 0); 85 switch(*ptr) { 86 case 'g': 87 case 'G': 88 BandwidthOpt *= 1024; 89 /* fall through */ 90 case 'm': 91 case 'M': 92 BandwidthOpt *= 1024; 93 /* fall through */ 94 case 'k': 95 case 'K': 96 BandwidthOpt *= 1024; 97 break; 98 case '\0': 99 /* bytes per second if no suffix */ 100 break; 101 default: 102 usage(1); 103 } 104 break; 105 case 'S': 106 SplitupOptStr = strdup(optarg); 107 SplitupOpt = strtoull(optarg, &ptr, 0); 108 switch(*ptr) { 109 case 'g': 110 case 'G': 111 SplitupOpt *= 1024; 112 /* fall through */ 113 case 'm': 114 case 'M': 115 SplitupOpt *= 1024; 116 /* fall through */ 117 case 'k': 118 case 'K': 119 SplitupOpt *= 1024; 120 break; 121 case '\0': 122 /* bytes per second if no suffix */ 123 break; 124 default: 125 usage(1); 126 } 127 break; 128 case 'c': 129 CyclePath = optarg; 130 break; 131 case 'd': 132 ++DebugOpt; 133 break; 134 case 'e': 135 ScoreBoardFile = optarg; 136 break; 137 case 'h': 138 usage(0); 139 /* not reached */ 140 case 'i': 141 DelayOpt = strtol(optarg, NULL, 0); 142 break; 143 case 'm': 144 MemoryLimit = strtouq(optarg, &ptr, 0); 145 switch(*ptr) { 146 case 't': 147 case 'T': 148 MemoryLimit *= 1024; 149 /* fall through */ 150 case 'g': 151 case 'G': 152 MemoryLimit *= 1024; 153 /* fall through */ 154 case 'm': 155 case 'M': 156 MemoryLimit *= 1024; 157 /* fall through */ 158 case 'k': 159 case 'K': 160 MemoryLimit *= 1024; 161 /* fall through */ 162 default: 163 break; 164 } 165 166 /* minimum limit */ 167 if (MemoryLimit < 1024 * 1024) 168 MemoryLimit = 1024 * 1024; 169 break; 170 case 'p': 171 SshPort = optarg; 172 break; 173 case 'r': 174 RecurseOpt = 1; 175 break; 176 case 'f': 177 blkdevs = optarg; 178 break; 179 case 't': 180 TimeoutOpt = strtol(optarg, NULL, 0); 181 break; 182 case 'v': 183 if (QuietOpt > 0) 184 --QuietOpt; 185 else 186 ++VerboseOpt; 187 break; 188 case 'q': 189 if (VerboseOpt > 0) 190 --VerboseOpt; 191 else 192 ++QuietOpt; 193 break; 194 case 'A': 195 AllPFS = 1; 196 break; 197 case 'B': 198 BulkOpt = 1; 199 break; 200 case 'C': 201 cacheSize = strtol(optarg, &ptr, 0); 202 switch(*ptr) { 203 case 'm': 204 case 'M': 205 cacheSize *= 1024; 206 /* fall through */ 207 case 'k': 208 case 'K': 209 cacheSize *= 1024; 210 ++ptr; 211 break; 212 case '\0': 213 case ':': 214 /* bytes if no suffix */ 215 break; 216 default: 217 usage(1); 218 } 219 if (*ptr == ':') { 220 UseReadAhead = strtol(ptr + 1, NULL, 0); 221 UseReadBehind = -UseReadAhead; 222 } 223 if (cacheSize < 1024 * 1024) 224 cacheSize = 1024 * 1024; 225 if (UseReadAhead < 0) 226 usage(1); 227 if (UseReadAhead * HAMMER_BUFSIZE / cacheSize / 16) { 228 UseReadAhead = cacheSize / 16 / HAMMER_BUFSIZE; 229 UseReadBehind = -UseReadAhead; 230 } 231 hammer_cache_set(cacheSize); 232 break; 233 case 'F': 234 ForceOpt = 1; 235 break; 236 case 'R': 237 if (restrictcmd == NULL) 238 restrictcmd = optarg; 239 break; 240 case 'T': 241 if (RestrictTarget == NULL) 242 RestrictTarget = optarg; 243 break; 244 case 'X': 245 CompressOpt = 1; 246 break; 247 default: 248 usage(1); 249 /* not reached */ 250 } 251 } 252 ac -= optind; 253 av += optind; 254 if (ac < 1) { 255 usage(1); 256 /* not reached */ 257 } 258 259 signal(SIGALRM, sigalrm); 260 signal(SIGINT, sigintr); 261 262 /* 263 * Check command restriction (used by hammer ssh-remote). Several 264 * commands may be iterated with a comma. 265 */ 266 if (restrictcmd) { 267 char *elm; 268 269 ptr = strdup(restrictcmd); 270 while ((elm = strsep(&ptr, ",")) != NULL) { 271 if (strcmp(av[0], elm) == 0) 272 break; 273 } 274 if (elm == NULL) { 275 fprintf(stderr, "hammer-remote: request does not match " 276 "restricted command\n"); 277 exit(1); 278 } 279 free(ptr); 280 } 281 282 /* 283 * Parse commands 284 */ 285 if (strcmp(av[0], "synctid") == 0) { 286 hammer_cmd_synctid(av + 1, ac - 1); 287 exit(0); 288 } 289 if (strcmp(av[0], "namekey2") == 0) { 290 int64_t key; 291 int32_t crcx; 292 int len; 293 const char *aname = av[1]; 294 295 if (aname == NULL) 296 usage(1); 297 len = strlen(aname); 298 key = (uint32_t)crc32(aname, len) & 0xFFFFFFFEU; 299 300 switch(len) { 301 default: 302 crcx = crc32(aname + 3, len - 5); 303 crcx = crcx ^ (crcx >> 6) ^ (crcx >> 12); 304 key |= (int64_t)(crcx & 0x3F) << 42; 305 /* fall through */ 306 case 5: 307 case 4: 308 /* fall through */ 309 case 3: 310 key |= ((int64_t)(aname[2] & 0x1F) << 48); 311 /* fall through */ 312 case 2: 313 key |= ((int64_t)(aname[1] & 0x1F) << 53) | 314 ((int64_t)(aname[len-2] & 0x1F) << 37); 315 /* fall through */ 316 case 1: 317 key |= ((int64_t)(aname[0] & 0x1F) << 58) | 318 ((int64_t)(aname[len-1] & 0x1F) << 32); 319 /* fall through */ 320 case 0: 321 break; 322 } 323 if (key == 0) 324 key |= 0x100000000LL; 325 printf("0x%016jx\n", (uintmax_t)key); 326 exit(0); 327 } 328 if (strcmp(av[0], "namekey1") == 0) { 329 int64_t key; 330 331 if (av[1] == NULL) 332 usage(1); 333 key = (int64_t)(crc32(av[1], strlen(av[1])) & 0x7FFFFFFF) << 32; 334 if (key == 0) 335 key |= 0x100000000LL; 336 printf("0x%016jx\n", (uintmax_t)key); 337 exit(0); 338 } 339 if (strcmp(av[0], "namekey32") == 0) { 340 int32_t key; 341 342 if (av[1] == NULL) 343 usage(1); 344 key = crc32(av[1], strlen(av[1])) & 0x7FFFFFFF; 345 if (key == 0) 346 ++key; 347 printf("0x%08x\n", key); 348 exit(0); 349 } 350 if (strcmp(av[0], "pfs-status") == 0) { 351 hammer_cmd_pseudofs_status(av + 1, ac - 1); 352 exit(0); 353 } 354 if (strcmp(av[0], "pfs-master") == 0) { 355 hammer_cmd_pseudofs_create(av + 1, ac - 1, 0); 356 exit(0); 357 } 358 if (strcmp(av[0], "pfs-slave") == 0) { 359 hammer_cmd_pseudofs_create(av + 1, ac - 1, 1); 360 exit(0); 361 } 362 if (strcmp(av[0], "pfs-update") == 0) { 363 hammer_cmd_pseudofs_update(av + 1, ac - 1); 364 exit(0); 365 } 366 if (strcmp(av[0], "pfs-upgrade") == 0) { 367 hammer_cmd_pseudofs_upgrade(av + 1, ac - 1); 368 exit(0); 369 } 370 if (strcmp(av[0], "pfs-downgrade") == 0) { 371 hammer_cmd_pseudofs_downgrade(av + 1, ac - 1); 372 exit(0); 373 } 374 if (strcmp(av[0], "pfs-destroy") == 0) { 375 hammer_cmd_pseudofs_destroy(av + 1, ac - 1); 376 exit(0); 377 } 378 if (strcmp(av[0], "prune") == 0) { 379 hammer_cmd_softprune(av + 1, ac - 1, 0); 380 exit(0); 381 } 382 if (strcmp(av[0], "config") == 0) { 383 hammer_cmd_config(av + 1, ac - 1); 384 exit(0); 385 } 386 if (strcmp(av[0], "viconfig") == 0) { 387 hammer_cmd_viconfig(av + 1, ac - 1); 388 exit(0); 389 } 390 if (strcmp(av[0], "cleanup") == 0) { 391 hammer_cmd_cleanup(av + 1, ac - 1); 392 exit(0); 393 } 394 if (strcmp(av[0], "abort-cleanup") == 0) { 395 hammer_cmd_abort_cleanup(av + 1, ac - 1); 396 exit(0); 397 } 398 if (strcmp(av[0], "info") == 0) { 399 hammer_cmd_info(av + 1, ac - 1); 400 exit(0); 401 } 402 if (strcmp(av[0], "prune-everything") == 0) { 403 hammer_cmd_softprune(av + 1, ac - 1, 1); 404 exit(0); 405 } 406 if (strcmp(av[0], "ssh-remote") == 0) { 407 if (ac != 3) 408 usage(1); 409 hammer_cmd_sshremote(av[1], av[2]); 410 exit(0); 411 } 412 if (strcmp(av[0], "snap") == 0) { 413 hammer_cmd_snap(av + 1, ac - 1, 0, 1); 414 exit(0); 415 } 416 if (strcmp(av[0], "snaplo") == 0) { 417 hammer_cmd_snap(av + 1, ac - 1, 0, 0); 418 exit(0); 419 } 420 if (strcmp(av[0], "snapq") == 0) { 421 hammer_cmd_snap(av + 1, ac - 1, 1, 0); 422 exit(0); 423 } 424 if (strcmp(av[0], "snapls") == 0) { 425 hammer_cmd_snapls(av + 1, ac - 1); 426 exit(0); 427 } 428 if (strcmp(av[0], "snaprm") == 0) { 429 hammer_cmd_snaprm(av + 1, ac - 1); 430 exit(0); 431 } 432 if (strcmp(av[0], "snapshot") == 0) { 433 hammer_cmd_snapshot(av + 1, ac - 1); 434 exit(0); 435 } 436 if (strcmp(av[0], "bstats") == 0) { 437 hammer_cmd_bstats(av + 1, ac - 1); 438 exit(0); 439 } 440 if (strcmp(av[0], "iostats") == 0) { 441 hammer_cmd_iostats(av + 1, ac - 1); 442 exit(0); 443 } 444 if (strcmp(av[0], "stats") == 0) { 445 hammer_cmd_stats(av + 1, ac - 1); 446 exit(0); 447 } 448 449 if (strncmp(av[0], "history", 7) == 0) { 450 hammer_cmd_history(av[0] + 7, av + 1, ac - 1); 451 exit(0); 452 } 453 if (strcmp(av[0], "rebalance") == 0) { 454 signal(SIGINT, sigalrm); 455 hammer_cmd_rebalance(av + 1, ac - 1); 456 exit(0); 457 } 458 if (strncmp(av[0], "reblock", 7) == 0) { 459 signal(SIGINT, sigalrm); 460 if (strcmp(av[0], "reblock") == 0) 461 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_FLAGS); 462 else if (strcmp(av[0], "reblock-btree") == 0) 463 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_BTREE); 464 else if (strcmp(av[0], "reblock-inodes") == 0) 465 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_INODES); 466 else if (strcmp(av[0], "reblock-dirs") == 0) 467 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DIRS); 468 else if (strcmp(av[0], "reblock-data") == 0) 469 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DATA); 470 else 471 usage(1); 472 exit(0); 473 } 474 if (strncmp(av[0], "mirror", 6) == 0) { 475 if (strcmp(av[0], "mirror-read") == 0) 476 hammer_cmd_mirror_read(av + 1, ac - 1, 0); 477 else if (strcmp(av[0], "mirror-read-stream") == 0) 478 hammer_cmd_mirror_read(av + 1, ac - 1, 1); 479 else if (strcmp(av[0], "mirror-write") == 0) 480 hammer_cmd_mirror_write(av + 1, ac - 1); 481 else if (strcmp(av[0], "mirror-copy") == 0) 482 hammer_cmd_mirror_copy(av + 1, ac - 1, 0); 483 else if (strcmp(av[0], "mirror-stream") == 0) 484 hammer_cmd_mirror_copy(av + 1, ac - 1, 1); 485 else if (strcmp(av[0], "mirror-dump") == 0) 486 hammer_cmd_mirror_dump(av + 1, ac - 1); 487 else 488 usage(1); 489 exit(0); 490 } 491 if (strcmp(av[0], "dedup-simulate") == 0) { 492 hammer_cmd_dedup_simulate(av + 1, ac - 1); 493 exit(0); 494 } 495 if (strcmp(av[0], "dedup") == 0) { 496 hammer_cmd_dedup(av + 1, ac - 1); 497 exit(0); 498 } 499 if (strcmp(av[0], "version") == 0) { 500 hammer_cmd_get_version(av + 1, ac - 1); 501 exit(0); 502 } 503 if (strcmp(av[0], "version-upgrade") == 0) { 504 hammer_cmd_set_version(av + 1, ac - 1); 505 exit(0); 506 } 507 if (strcmp(av[0], "volume-add") == 0) { 508 hammer_cmd_volume_add(av + 1, ac - 1); 509 exit(0); 510 } 511 if (strcmp(av[0], "volume-del") == 0) { 512 hammer_cmd_volume_del(av + 1, ac - 1); 513 exit(0); 514 } 515 if (strcmp(av[0], "volume-list") == 0) { 516 hammer_cmd_volume_list(av + 1, ac - 1, av[0]); 517 exit(0); 518 } 519 if (strcmp(av[0], "volume-blkdevs") == 0) { 520 hammer_cmd_volume_blkdevs(av + 1, ac - 1, av[0]); 521 exit(0); 522 } 523 524 uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status); 525 if (status != uuid_s_ok) { 526 errx(1, "uuids file does not have the DragonFly " 527 "HAMMER filesystem type"); 528 } 529 530 if (strcmp(av[0], "show") == 0) { 531 const char *arg = NULL; 532 int filter = -1; 533 534 hammer_parsedevs(blkdevs); 535 if (ac > 1) 536 arg = av[1]; 537 if (ac > 2) { 538 if (strcmp(av[2], "filter") == 0) 539 filter = 1; 540 else if (strcmp(av[2], "nofilter") == 0) 541 filter = 0; 542 } 543 hammer_cmd_show(-1, arg, filter, 0, NULL, NULL); 544 exit(0); 545 } 546 if (strcmp(av[0], "show-undo") == 0) { 547 hammer_parsedevs(blkdevs); 548 hammer_cmd_show_undo(); 549 exit(0); 550 } 551 if (strcmp(av[0], "recover") == 0) { 552 hammer_parsedevs(blkdevs); 553 if (ac <= 1) 554 errx(1, "hammer recover required target directory"); 555 hammer_cmd_recover(av[1]); 556 exit(0); 557 } 558 if (strcmp(av[0], "blockmap") == 0) { 559 hammer_parsedevs(blkdevs); 560 hammer_cmd_blockmap(); 561 exit(0); 562 } 563 if (strcmp(av[0], "checkmap") == 0) { 564 hammer_parsedevs(blkdevs); 565 hammer_cmd_checkmap(); 566 exit(0); 567 } 568 usage(1); 569 /* not reached */ 570 return(0); 571 } 572 573 /* 574 * Parse the device specification. 575 * 576 * Multi-volume hammer devices are colon-separated. Each element 577 * may be further expanded via /etc/devtab. One may also specify 578 * a single element which is expanded into multiple elements via 579 * /etc/devtab. 580 */ 581 static 582 void 583 hammer_parsedevs(const char *blkdevs) 584 { 585 struct volume_info *vol = NULL; 586 char *copy; 587 char *volname; 588 int volnum = 0; 589 590 if (blkdevs == NULL) { 591 errx(1, "A -f blkdevs specification is required " 592 "for this command"); 593 } 594 595 copy = strdup(blkdevs); 596 while ((volname = copy) != NULL) { 597 if ((copy = strchr(copy, ':')) != NULL) 598 *copy++ = 0; 599 volname = getdevpath(volname, 0); 600 if (strchr(volname, ':')) 601 hammer_parsedevs(volname); 602 else { 603 vol = setup_volume(-1, volname, 0, O_RDONLY); 604 assert(vol); 605 ++volnum; 606 } 607 free(volname); 608 } 609 free(copy); 610 611 /* 612 * All volumes have the same vol_count. 613 */ 614 assert(vol); 615 if (volnum != vol->ondisk->vol_count) 616 errx(1, "Volume header says %d volumes, but %d specified.", 617 vol->ondisk->vol_count, volnum); 618 } 619 620 static 621 void 622 sigalrm(int signo __unused) 623 { 624 /* do nothing (interrupts HAMMER ioctl) */ 625 } 626 627 static 628 void 629 sigintr(int signo __unused) 630 { 631 if (RunningIoctl == 0) 632 _exit(1); 633 DidInterrupt = 1; 634 /* do nothing (interrupts HAMMER ioctl) */ 635 } 636 637 static 638 void 639 usage(int exit_code) 640 { 641 fprintf(stderr, 642 "hammer -h\n" 643 "hammer [-2ABFqrvXy] [-b bandwidth] [-C cachesize[:readahead]] \n" 644 " [-R restrictcmd] [-T restrictpath] [-c cyclefile]\n" 645 " [-e scoreboardfile] [-f blkdevs] [-i delay] [-p ssh-port]\n" 646 " [-S splitsize] [-t seconds] [-m memlimit] command [argument ...]\n" 647 "hammer synctid <filesystem> [quick]\n" 648 "hammer bstats [interval]\n" 649 "hammer iostats [interval]\n" 650 "hammer stats [interval]\n" 651 "hammer history[@offset[,len]] <file> ...\n" 652 "hammer namekey1 <path>\n" 653 "hammer namekey2 <path>\n" 654 "hammer namekey32 <path>\n" 655 "hammer cleanup [<filesystem> ...]\n" 656 "hammer abort-cleanup\n" 657 "hammer info [<dirpath> ...]\n" 658 "hammer snapshot [<filesystem>] <snapshot-dir>\n" 659 "hammer snapshot <filesystem> <snapshot-dir> [<note>]\n" 660 "hammer prune <softlink-dir>\n" 661 "hammer prune-everything <filesystem>\n" 662 "hammer rebalance <filesystem> [saturation_percentage]\n" 663 "hammer reblock[-btree|-inodes|-dirs|-data] " 664 "<filesystem> [fill_percentage]\n" 665 "hammer pfs-status <dirpath> ...\n" 666 "hammer pfs-master <dirpath> [options]\n" 667 "hammer pfs-slave <dirpath> [options]\n" 668 "hammer pfs-update <dirpath> [options]\n" 669 "hammer pfs-upgrade <dirpath>\n" 670 "hammer pfs-downgrade <dirpath>\n" 671 "hammer pfs-destroy <dirpath>\n" 672 "hammer mirror-read <filesystem> [begin-tid]\n" 673 "hammer mirror-read-stream <filesystem> [begin-tid]\n" 674 "hammer mirror-write <filesystem>\n" 675 "hammer mirror-dump [header]\n" 676 "hammer mirror-copy [[user@]host:]<filesystem>" 677 " [[user@]host:]<filesystem>\n" 678 "hammer mirror-stream [[user@]host:]<filesystem>" 679 " [[user@]host:]<filesystem>\n" 680 "hammer ssh-remote command filesystem\n" 681 "hammer version <filesystem>\n" 682 "hammer version-upgrade <filesystem> <version> [force]\n" 683 "hammer volume-add <device> <filesystem>\n" 684 "hammer volume-del <device> <filesystem>\n" 685 "hammer volume-list <filesystem>\n" 686 "hammer volume-blkdevs <filesystem>\n" 687 ); 688 689 fprintf(stderr, "\nHAMMER utility version 3+ commands:\n"); 690 691 fprintf(stderr, 692 "hammer config [<filesystem> [<configfile>]]\n" 693 "hammer viconfig [<filesystem>]\n" 694 "hammer snap <path> [<note>]\n" 695 "hammer snaplo <path> [<note>]\n" 696 "hammer snapq <dir> [<note>]\n" 697 "hammer snaprm <path> ...\n" 698 "hammer snaprm <transid> ...\n" 699 "hammer snaprm <filesystem> <transid> ...\n" 700 "hammer snapls [<path> ...]\n" 701 ); 702 703 fprintf(stderr, "\nHAMMER utility version 4+ commands:\n"); 704 705 fprintf(stderr, 706 "hammer -f blkdevs blockmap\n" 707 "hammer -f blkdevs checkmap\n" 708 "hammer -f blkdevs [-qqq] show [lo:objid]\n" 709 "hammer -f blkdevs show-undo\n" 710 "hammer -f blkdevs recover <target_dir>\n" 711 ); 712 713 fprintf(stderr, "\nHAMMER utility version 5+ commands:\n"); 714 715 fprintf(stderr, 716 "hammer dedup-simulate <filesystem>\n" 717 "hammer dedup <filesystem>\n" 718 ); 719 720 exit(exit_code); 721 } 722 723