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