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