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