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; 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 uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status); 283 if (status != uuid_s_ok) { 284 errx(1, "uuids file does not have the DragonFly " 285 "HAMMER filesystem type"); 286 } 287 288 /* 289 * Parse commands 290 */ 291 if (strcmp(av[0], "synctid") == 0) { 292 hammer_cmd_synctid(av + 1, ac - 1); 293 exit(0); 294 } 295 if (strcmp(av[0], "namekey2") == 0) { 296 int64_t key; 297 int32_t crcx; 298 int len; 299 const char *aname = av[1]; 300 301 if (aname == NULL) 302 usage(1); 303 len = strlen(aname); 304 key = (uint32_t)crc32(aname, len) & 0xFFFFFFFEU; 305 306 switch(len) { 307 default: 308 crcx = crc32(aname + 3, len - 5); 309 crcx = crcx ^ (crcx >> 6) ^ (crcx >> 12); 310 key |= (int64_t)(crcx & 0x3F) << 42; 311 /* fall through */ 312 case 5: 313 case 4: 314 /* fall through */ 315 case 3: 316 key |= ((int64_t)(aname[2] & 0x1F) << 48); 317 /* fall through */ 318 case 2: 319 key |= ((int64_t)(aname[1] & 0x1F) << 53) | 320 ((int64_t)(aname[len-2] & 0x1F) << 37); 321 /* fall through */ 322 case 1: 323 key |= ((int64_t)(aname[0] & 0x1F) << 58) | 324 ((int64_t)(aname[len-1] & 0x1F) << 32); 325 /* fall through */ 326 case 0: 327 break; 328 } 329 if (key == 0) 330 key |= 0x100000000LL; 331 printf("0x%016jx\n", (uintmax_t)key); 332 exit(0); 333 } 334 if (strcmp(av[0], "namekey1") == 0) { 335 int64_t key; 336 337 if (av[1] == NULL) 338 usage(1); 339 key = (int64_t)(crc32(av[1], strlen(av[1])) & 0x7FFFFFFF) << 32; 340 if (key == 0) 341 key |= 0x100000000LL; 342 printf("0x%016jx\n", (uintmax_t)key); 343 exit(0); 344 } 345 if (strcmp(av[0], "namekey32") == 0) { 346 int32_t key; 347 348 if (av[1] == NULL) 349 usage(1); 350 key = crc32(av[1], strlen(av[1])) & 0x7FFFFFFF; 351 if (key == 0) 352 ++key; 353 printf("0x%08x\n", key); 354 exit(0); 355 } 356 if (strcmp(av[0], "pfs-status") == 0) { 357 hammer_cmd_pseudofs_status(av + 1, ac - 1); 358 exit(0); 359 } 360 if (strcmp(av[0], "pfs-master") == 0) { 361 hammer_cmd_pseudofs_create(av + 1, ac - 1, 0); 362 exit(0); 363 } 364 if (strcmp(av[0], "pfs-slave") == 0) { 365 hammer_cmd_pseudofs_create(av + 1, ac - 1, 1); 366 exit(0); 367 } 368 if (strcmp(av[0], "pfs-update") == 0) { 369 hammer_cmd_pseudofs_update(av + 1, ac - 1); 370 exit(0); 371 } 372 if (strcmp(av[0], "pfs-upgrade") == 0) { 373 hammer_cmd_pseudofs_upgrade(av + 1, ac - 1); 374 exit(0); 375 } 376 if (strcmp(av[0], "pfs-downgrade") == 0) { 377 hammer_cmd_pseudofs_downgrade(av + 1, ac - 1); 378 exit(0); 379 } 380 if (strcmp(av[0], "pfs-destroy") == 0) { 381 hammer_cmd_pseudofs_destroy(av + 1, ac - 1); 382 exit(0); 383 } 384 if (strcmp(av[0], "prune") == 0) { 385 hammer_cmd_softprune(av + 1, ac - 1, 0); 386 exit(0); 387 } 388 if (strcmp(av[0], "config") == 0) { 389 hammer_cmd_config(av + 1, ac - 1); 390 exit(0); 391 } 392 if (strcmp(av[0], "viconfig") == 0) { 393 hammer_cmd_viconfig(av + 1, ac - 1); 394 exit(0); 395 } 396 if (strcmp(av[0], "cleanup") == 0) { 397 hammer_cmd_cleanup(av + 1, ac - 1); 398 exit(0); 399 } 400 if (strcmp(av[0], "abort-cleanup") == 0) { 401 hammer_cmd_abort_cleanup(av + 1, ac - 1); 402 exit(0); 403 } 404 if (strcmp(av[0], "info") == 0) { 405 hammer_cmd_info(av + 1, ac - 1); 406 exit(0); 407 } 408 if (strcmp(av[0], "prune-everything") == 0) { 409 hammer_cmd_softprune(av + 1, ac - 1, 1); 410 exit(0); 411 } 412 if (strcmp(av[0], "ssh-remote") == 0) { 413 if (ac != 3) 414 usage(1); 415 hammer_cmd_sshremote(av[1], av[2]); 416 exit(0); 417 } 418 if (strcmp(av[0], "snap") == 0) { 419 hammer_cmd_snap(av + 1, ac - 1, 0, 1); 420 exit(0); 421 } 422 if (strcmp(av[0], "snaplo") == 0) { 423 hammer_cmd_snap(av + 1, ac - 1, 0, 0); 424 exit(0); 425 } 426 if (strcmp(av[0], "snapq") == 0) { 427 hammer_cmd_snap(av + 1, ac - 1, 1, 0); 428 exit(0); 429 } 430 if (strcmp(av[0], "snapls") == 0) { 431 hammer_cmd_snapls(av + 1, ac - 1); 432 exit(0); 433 } 434 if (strcmp(av[0], "snaprm") == 0) { 435 hammer_cmd_snaprm(av + 1, ac - 1); 436 exit(0); 437 } 438 if (strcmp(av[0], "snapshot") == 0) { 439 hammer_cmd_snapshot(av + 1, ac - 1); 440 exit(0); 441 } 442 if (strcmp(av[0], "bstats") == 0) { 443 hammer_cmd_bstats(av + 1, ac - 1); 444 exit(0); 445 } 446 if (strcmp(av[0], "iostats") == 0) { 447 hammer_cmd_iostats(av + 1, ac - 1); 448 exit(0); 449 } 450 if (strcmp(av[0], "stats") == 0) { 451 hammer_cmd_stats(av + 1, ac - 1); 452 exit(0); 453 } 454 455 if (strncmp(av[0], "history", 7) == 0) { 456 hammer_cmd_history(av[0] + 7, av + 1, ac - 1); 457 exit(0); 458 } 459 if (strcmp(av[0], "rebalance") == 0) { 460 signal(SIGINT, sigalrm); 461 hammer_cmd_rebalance(av + 1, ac - 1); 462 exit(0); 463 } 464 if (strncmp(av[0], "reblock", 7) == 0) { 465 signal(SIGINT, sigalrm); 466 if (strcmp(av[0], "reblock") == 0) 467 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_FLAGS); 468 else if (strcmp(av[0], "reblock-btree") == 0) 469 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_BTREE); 470 else if (strcmp(av[0], "reblock-inodes") == 0) 471 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_INODES); 472 else if (strcmp(av[0], "reblock-dirs") == 0) 473 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DIRS); 474 else if (strcmp(av[0], "reblock-data") == 0) 475 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DATA); 476 else 477 usage(1); 478 exit(0); 479 } 480 if (strncmp(av[0], "mirror", 6) == 0) { 481 if (strcmp(av[0], "mirror-read") == 0) 482 hammer_cmd_mirror_read(av + 1, ac - 1, 0); 483 else if (strcmp(av[0], "mirror-read-stream") == 0) 484 hammer_cmd_mirror_read(av + 1, ac - 1, 1); 485 else if (strcmp(av[0], "mirror-write") == 0) 486 hammer_cmd_mirror_write(av + 1, ac - 1); 487 else if (strcmp(av[0], "mirror-copy") == 0) 488 hammer_cmd_mirror_copy(av + 1, ac - 1, 0); 489 else if (strcmp(av[0], "mirror-stream") == 0) 490 hammer_cmd_mirror_copy(av + 1, ac - 1, 1); 491 else if (strcmp(av[0], "mirror-dump") == 0) 492 hammer_cmd_mirror_dump(av + 1, ac - 1); 493 else 494 usage(1); 495 exit(0); 496 } 497 if (strcmp(av[0], "dedup-simulate") == 0) { 498 hammer_cmd_dedup_simulate(av + 1, ac - 1); 499 exit(0); 500 } 501 if (strcmp(av[0], "dedup") == 0) { 502 hammer_cmd_dedup(av + 1, ac - 1); 503 exit(0); 504 } 505 if (strcmp(av[0], "version") == 0) { 506 hammer_cmd_get_version(av + 1, ac - 1); 507 exit(0); 508 } 509 if (strcmp(av[0], "version-upgrade") == 0) { 510 hammer_cmd_set_version(av + 1, ac - 1); 511 exit(0); 512 } 513 if (strcmp(av[0], "volume-add") == 0) { 514 hammer_cmd_volume_add(av + 1, ac - 1); 515 exit(0); 516 } 517 if (strcmp(av[0], "volume-del") == 0) { 518 hammer_cmd_volume_del(av + 1, ac - 1); 519 exit(0); 520 } 521 if (strcmp(av[0], "volume-list") == 0) { 522 hammer_cmd_volume_list(av + 1, ac - 1); 523 exit(0); 524 } 525 if (strcmp(av[0], "volume-blkdevs") == 0) { 526 hammer_cmd_volume_blkdevs(av + 1, ac - 1); 527 exit(0); 528 } 529 530 if (strcmp(av[0], "show") == 0) { 531 const char *arg = NULL; 532 int filter = -1; 533 int obfuscate = 0; 534 int indent = 0; 535 536 hammer_parsedevs(blkdevs); 537 if (ac > 3) 538 errx(1, "Too many options specified"); 539 if (ac > 1) 540 arg = av[1]; 541 if (ac > 2) { 542 char *p, *buf = strdup(av[2]); 543 while((p = strsep(&buf, ",")) != NULL) { 544 if (strcmp(p, "filter") == 0) { 545 filter = 1; 546 } else if (strcmp(p, "nofilter") == 0) { 547 filter = 0; 548 } else if (strcmp(p, "obfuscate") == 0) { 549 obfuscate = 1; 550 } else if (strcmp(p, "indent") == 0) { 551 indent = 1; 552 } 553 } 554 free(buf); 555 } 556 hammer_cmd_show(arg, filter, obfuscate, indent); 557 exit(0); 558 } 559 if (strcmp(av[0], "show-undo") == 0) { 560 hammer_parsedevs(blkdevs); 561 hammer_cmd_show_undo(); 562 exit(0); 563 } 564 if (strcmp(av[0], "recover") == 0) { 565 hammer_parsedevs(blkdevs); 566 if (ac <= 1) 567 errx(1, "hammer recover required target directory"); 568 hammer_cmd_recover(av[1]); 569 exit(0); 570 } 571 if (strcmp(av[0], "blockmap") == 0) { 572 hammer_parsedevs(blkdevs); 573 hammer_cmd_blockmap(); 574 exit(0); 575 } 576 if (strcmp(av[0], "checkmap") == 0) { 577 hammer_parsedevs(blkdevs); 578 hammer_cmd_checkmap(); 579 exit(0); 580 } 581 usage(1); 582 /* not reached */ 583 return(0); 584 } 585 586 /* 587 * Parse the device specification. 588 * 589 * Multi-volume hammer devices are colon-separated. Each element 590 * may be further expanded via /etc/devtab. One may also specify 591 * a single element which is expanded into multiple elements via 592 * /etc/devtab. 593 */ 594 static 595 void 596 hammer_parsedevs(const char *blkdevs) 597 { 598 struct volume_info *vol = NULL; 599 char *copy; 600 char *volname; 601 int volnum = 0; 602 603 if (blkdevs == NULL) { 604 errx(1, "A -f blkdevs specification is required " 605 "for this command"); 606 } 607 608 copy = strdup(blkdevs); 609 while ((volname = copy) != NULL) { 610 if ((copy = strchr(copy, ':')) != NULL) 611 *copy++ = 0; 612 volname = getdevpath(volname, 0); 613 if (strchr(volname, ':')) 614 hammer_parsedevs(volname); 615 else { 616 vol = load_volume(volname, O_RDONLY); 617 assert(vol); 618 ++volnum; 619 } 620 free(volname); 621 } 622 free(copy); 623 624 /* 625 * All volumes have the same vol_count. 626 */ 627 assert(vol); 628 if (volnum != vol->ondisk->vol_count) 629 errx(1, "Volume header says %d volumes, but %d specified.", 630 vol->ondisk->vol_count, volnum); 631 632 if (get_root_volume() == NULL) 633 errx(1, "No root volume found"); 634 } 635 636 static 637 void 638 sigalrm(int signo __unused) 639 { 640 /* do nothing (interrupts HAMMER ioctl) */ 641 } 642 643 static 644 void 645 sigintr(int signo __unused) 646 { 647 if (RunningIoctl == 0) 648 _exit(1); 649 DidInterrupt = 1; 650 /* do nothing (interrupts HAMMER ioctl) */ 651 } 652 653 static 654 void 655 usage(int exit_code) 656 { 657 fprintf(stderr, 658 "hammer -h\n" 659 "hammer [-2ABFqrvXy] [-b bandwidth] [-C cachesize[:readahead]] \n" 660 " [-R restrictcmd] [-T restrictpath] [-c cyclefile]\n" 661 " [-e scoreboardfile] [-f blkdevs] [-i delay] [-p ssh-port]\n" 662 " [-S splitsize] [-t seconds] [-m memlimit] command [argument ...]\n" 663 "hammer synctid <filesystem> [quick]\n" 664 "hammer bstats [interval]\n" 665 "hammer iostats [interval]\n" 666 "hammer stats [interval]\n" 667 "hammer history[@offset[,len]] <file> ...\n" 668 "hammer namekey1 <path>\n" 669 "hammer namekey2 <path>\n" 670 "hammer namekey32 <path>\n" 671 "hammer cleanup [<filesystem> ...]\n" 672 "hammer abort-cleanup\n" 673 "hammer info [<dirpath> ...]\n" 674 "hammer snapshot [<filesystem>] <snapshot-dir>\n" 675 "hammer snapshot <filesystem> <snapshot-dir> [<note>]\n" 676 "hammer prune <softlink-dir>\n" 677 "hammer prune-everything <filesystem>\n" 678 "hammer rebalance <filesystem> [saturation_percentage]\n" 679 "hammer reblock[-btree|-inodes|-dirs|-data] " 680 "<filesystem> [fill_percentage]\n" 681 "hammer pfs-status <dirpath> ...\n" 682 "hammer pfs-master <dirpath> [options]\n" 683 "hammer pfs-slave <dirpath> [options]\n" 684 "hammer pfs-update <dirpath> [options]\n" 685 "hammer pfs-upgrade <dirpath>\n" 686 "hammer pfs-downgrade <dirpath>\n" 687 "hammer pfs-destroy <dirpath>\n" 688 "hammer mirror-read <filesystem> [begin-tid]\n" 689 "hammer mirror-read-stream <filesystem> [begin-tid]\n" 690 "hammer mirror-write <filesystem>\n" 691 "hammer mirror-dump [header]\n" 692 "hammer mirror-copy [[user@]host:]<filesystem>" 693 " [[user@]host:]<filesystem>\n" 694 "hammer mirror-stream [[user@]host:]<filesystem>" 695 " [[user@]host:]<filesystem>\n" 696 "hammer ssh-remote command filesystem\n" 697 "hammer version <filesystem>\n" 698 "hammer version-upgrade <filesystem> <version> [force]\n" 699 "hammer volume-add <device> <filesystem>\n" 700 "hammer volume-del <device> <filesystem>\n" 701 "hammer volume-list <filesystem>\n" 702 "hammer volume-blkdevs <filesystem>\n" 703 ); 704 705 fprintf(stderr, "\nHAMMER utility version 3+ commands:\n"); 706 707 fprintf(stderr, 708 "hammer config [<filesystem> [<configfile>]]\n" 709 "hammer viconfig [<filesystem>]\n" 710 "hammer snap <path> [<note>]\n" 711 "hammer snaplo <path> [<note>]\n" 712 "hammer snapq <dir> [<note>]\n" 713 "hammer snaprm <path> ...\n" 714 "hammer snaprm <transid> ...\n" 715 "hammer snaprm <filesystem> <transid> ...\n" 716 "hammer snapls [<path> ...]\n" 717 ); 718 719 fprintf(stderr, "\nHAMMER utility version 4+ commands:\n"); 720 721 fprintf(stderr, 722 "hammer -f blkdevs blockmap\n" 723 "hammer -f blkdevs checkmap\n" 724 "hammer -f blkdevs [-qqq] show [lo:objid]\n" 725 "hammer -f blkdevs show-undo\n" 726 "hammer -f blkdevs recover <target_dir>\n" 727 ); 728 729 fprintf(stderr, "\nHAMMER utility version 5+ commands:\n"); 730 731 fprintf(stderr, 732 "hammer dedup-simulate <filesystem>\n" 733 "hammer dedup <filesystem>\n" 734 ); 735 736 exit(exit_code); 737 } 738 739