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 * $DragonFly: src/sbin/hammer/hammer.c,v 1.44 2008/11/13 02:04:27 dillon Exp $ 35 */ 36 37 #include "hammer.h" 38 #include <signal.h> 39 #include <math.h> 40 41 static void hammer_parsedevs(const char *blkdevs); 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 int ForceYesOpt = 0; 54 int RunningIoctl; 55 int DidInterrupt; 56 u_int64_t BandwidthOpt; 57 const char *CyclePath; 58 const char *LinkPath; 59 60 int 61 main(int ac, char **av) 62 { 63 char *blkdevs = NULL; 64 char *ptr; 65 u_int32_t status; 66 int ch; 67 int cacheSize = 0; 68 69 while ((ch = getopt(ac, av, "b:c:dhf:i:qrs:t:v2yC:")) != -1) { 70 switch(ch) { 71 case '2': 72 TwoWayPipeOpt = 1; 73 break; 74 case 'y': 75 ForceYesOpt = 1; 76 break; 77 case 'b': 78 BandwidthOpt = strtoull(optarg, &ptr, 0); 79 switch(*ptr) { 80 case 'g': 81 case 'G': 82 BandwidthOpt *= 1024; 83 /* fall through */ 84 case 'm': 85 case 'M': 86 BandwidthOpt *= 1024; 87 /* fall through */ 88 case 'k': 89 case 'K': 90 BandwidthOpt *= 1024; 91 break; 92 case '\0': 93 /* bytes per second if no suffix */ 94 break; 95 default: 96 usage(1); 97 } 98 break; 99 case 'c': 100 CyclePath = optarg; 101 break; 102 case 'd': 103 ++DebugOpt; 104 break; 105 case 'h': 106 usage(0); 107 /* not reached */ 108 case 'i': 109 DelayOpt = strtol(optarg, NULL, 0); 110 break; 111 case 'r': 112 RecurseOpt = 1; 113 break; 114 case 'f': 115 blkdevs = optarg; 116 break; 117 case 's': 118 LinkPath = optarg; 119 break; 120 case 't': 121 TimeoutOpt = strtol(optarg, NULL, 0); 122 break; 123 case 'v': 124 if (QuietOpt > 0) 125 --QuietOpt; 126 else 127 ++VerboseOpt; 128 break; 129 case 'q': 130 if (VerboseOpt > 0) 131 --VerboseOpt; 132 else 133 ++QuietOpt; 134 break; 135 case 'C': 136 cacheSize = strtol(optarg, &ptr, 0); 137 switch(*ptr) { 138 case 'm': 139 case 'M': 140 cacheSize *= 1024; 141 /* fall through */ 142 case 'k': 143 case 'K': 144 cacheSize *= 1024; 145 ++ptr; 146 break; 147 case '\0': 148 case ':': 149 /* bytes if no suffix */ 150 break; 151 default: 152 usage(1); 153 } 154 if (*ptr == ':') { 155 UseReadAhead = strtol(ptr + 1, NULL, 0); 156 UseReadBehind = -UseReadAhead; 157 } 158 if (cacheSize < 1024 * 1024) 159 cacheSize = 1024 * 1024; 160 if (UseReadAhead < 0) 161 usage(1); 162 if (UseReadAhead * HAMMER_BUFSIZE / cacheSize / 16) { 163 UseReadAhead = cacheSize / 16 / HAMMER_BUFSIZE; 164 UseReadBehind = -UseReadAhead; 165 } 166 hammer_cache_set(cacheSize); 167 break; 168 default: 169 usage(1); 170 /* not reached */ 171 } 172 } 173 ac -= optind; 174 av += optind; 175 if (ac < 1) { 176 usage(1); 177 /* not reached */ 178 } 179 180 signal(SIGALRM, sigalrm); 181 signal(SIGINT, sigintr); 182 183 if (strcmp(av[0], "synctid") == 0) { 184 hammer_cmd_synctid(av + 1, ac - 1); 185 exit(0); 186 } 187 if (strcmp(av[0], "namekey2") == 0) { 188 int64_t key; 189 int32_t crcx; 190 int len; 191 const char *aname = av[1]; 192 193 if (aname == NULL) 194 usage(1); 195 len = strlen(aname); 196 key = (u_int32_t)crc32(aname, len) & 0xFFFFFFFEU; 197 198 switch(len) { 199 default: 200 crcx = crc32(aname + 3, len - 5); 201 crcx = crcx ^ (crcx >> 6) ^ (crcx >> 12); 202 key |= (int64_t)(crcx & 0x3F) << 42; 203 /* fall through */ 204 case 5: 205 case 4: 206 /* fall through */ 207 case 3: 208 key |= ((int64_t)(aname[2] & 0x1F) << 48); 209 /* fall through */ 210 case 2: 211 key |= ((int64_t)(aname[1] & 0x1F) << 53) | 212 ((int64_t)(aname[len-2] & 0x1F) << 37); 213 /* fall through */ 214 case 1: 215 key |= ((int64_t)(aname[0] & 0x1F) << 58) | 216 ((int64_t)(aname[len-1] & 0x1F) << 32); 217 /* fall through */ 218 case 0: 219 break; 220 } 221 if (key == 0) 222 key |= 0x100000000LL; 223 printf("0x%016llx\n", key); 224 exit(0); 225 } 226 if (strcmp(av[0], "namekey1") == 0) { 227 int64_t key; 228 229 if (av[1] == NULL) 230 usage(1); 231 key = (int64_t)(crc32(av[1], strlen(av[1])) & 0x7FFFFFFF) << 32; 232 if (key == 0) 233 key |= 0x100000000LL; 234 printf("0x%016llx\n", key); 235 exit(0); 236 } 237 if (strcmp(av[0], "namekey32") == 0) { 238 int32_t key; 239 240 if (av[1] == NULL) 241 usage(1); 242 key = crc32(av[1], strlen(av[1])) & 0x7FFFFFFF; 243 if (key == 0) 244 ++key; 245 printf("0x%08x\n", key); 246 exit(0); 247 } 248 if (strcmp(av[0], "pfs-status") == 0) { 249 hammer_cmd_pseudofs_status(av + 1, ac - 1); 250 exit(0); 251 } 252 if (strcmp(av[0], "pfs-master") == 0) { 253 hammer_cmd_pseudofs_create(av + 1, ac - 1, 0); 254 exit(0); 255 } 256 if (strcmp(av[0], "pfs-slave") == 0) { 257 hammer_cmd_pseudofs_create(av + 1, ac - 1, 1); 258 exit(0); 259 } 260 if (strcmp(av[0], "pfs-update") == 0) { 261 hammer_cmd_pseudofs_update(av + 1, ac - 1); 262 exit(0); 263 } 264 if (strcmp(av[0], "pfs-upgrade") == 0) { 265 hammer_cmd_pseudofs_upgrade(av + 1, ac - 1); 266 exit(0); 267 } 268 if (strcmp(av[0], "pfs-downgrade") == 0) { 269 hammer_cmd_pseudofs_downgrade(av + 1, ac - 1); 270 exit(0); 271 } 272 if (strcmp(av[0], "pfs-destroy") == 0) { 273 hammer_cmd_pseudofs_destroy(av + 1, ac - 1); 274 exit(0); 275 } 276 if (strcmp(av[0], "status") == 0) { 277 hammer_cmd_status(av + 1, ac - 1); 278 exit(0); 279 } 280 if (strcmp(av[0], "prune") == 0) { 281 hammer_cmd_softprune(av + 1, ac - 1, 0); 282 exit(0); 283 } 284 if (strcmp(av[0], "cleanup") == 0) { 285 hammer_cmd_cleanup(av + 1, ac - 1); 286 exit(0); 287 } 288 if (strcmp(av[0], "prune-everything") == 0) { 289 hammer_cmd_softprune(av + 1, ac - 1, 1); 290 exit(0); 291 } 292 if (strcmp(av[0], "snapshot") == 0) { 293 hammer_cmd_snapshot(av + 1, ac - 1); 294 exit(0); 295 } 296 if (strcmp(av[0], "bstats") == 0) { 297 hammer_cmd_bstats(av + 1, ac - 1); 298 exit(0); 299 } 300 if (strcmp(av[0], "iostats") == 0) { 301 hammer_cmd_iostats(av + 1, ac - 1); 302 exit(0); 303 } 304 305 if (strncmp(av[0], "history", 7) == 0) { 306 hammer_cmd_history(av[0] + 7, av + 1, ac - 1); 307 exit(0); 308 } 309 if (strcmp(av[0], "rebalance") == 0) { 310 signal(SIGINT, sigalrm); 311 hammer_cmd_rebalance(av + 1, ac - 1); 312 exit(0); 313 } 314 if (strncmp(av[0], "reblock", 7) == 0) { 315 signal(SIGINT, sigalrm); 316 if (strcmp(av[0], "reblock") == 0) 317 hammer_cmd_reblock(av + 1, ac - 1, -1); 318 else if (strcmp(av[0], "reblock-btree") == 0) 319 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_BTREE); 320 else if (strcmp(av[0], "reblock-inodes") == 0) 321 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_INODES); 322 else if (strcmp(av[0], "reblock-dirs") == 0) 323 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DIRS); 324 else if (strcmp(av[0], "reblock-data") == 0) 325 hammer_cmd_reblock(av + 1, ac - 1, HAMMER_IOC_DO_DATA); 326 else 327 usage(1); 328 exit(0); 329 } 330 if (strncmp(av[0], "mirror", 6) == 0) { 331 if (strcmp(av[0], "mirror-read") == 0) 332 hammer_cmd_mirror_read(av + 1, ac - 1, 0); 333 else if (strcmp(av[0], "mirror-read-stream") == 0) 334 hammer_cmd_mirror_read(av + 1, ac - 1, 1); 335 else if (strcmp(av[0], "mirror-write") == 0) 336 hammer_cmd_mirror_write(av + 1, ac - 1); 337 else if (strcmp(av[0], "mirror-copy") == 0) 338 hammer_cmd_mirror_copy(av + 1, ac - 1, 0); 339 else if (strcmp(av[0], "mirror-stream") == 0) 340 hammer_cmd_mirror_copy(av + 1, ac - 1, 1); 341 else if (strcmp(av[0], "mirror-dump") == 0) 342 hammer_cmd_mirror_dump(); 343 else 344 usage(1); 345 exit(0); 346 } 347 if (strcmp(av[0], "version") == 0) { 348 hammer_cmd_get_version(av + 1, ac - 1); 349 exit(0); 350 } 351 if (strcmp(av[0], "version-upgrade") == 0) { 352 hammer_cmd_set_version(av + 1, ac - 1); 353 exit(0); 354 } 355 356 uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status); 357 if (status != uuid_s_ok) { 358 errx(1, "uuids file does not have the DragonFly " 359 "HAMMER filesystem type"); 360 } 361 362 if (strcmp(av[0], "show") == 0) { 363 hammer_off_t node_offset = (hammer_off_t)-1; 364 365 hammer_parsedevs(blkdevs); 366 if (ac > 1) 367 sscanf(av[1], "%llx", &node_offset); 368 hammer_cmd_show(node_offset, 0, NULL, NULL); 369 exit(0); 370 } 371 if (strcmp(av[0], "blockmap") == 0) { 372 hammer_parsedevs(blkdevs); 373 hammer_cmd_blockmap(); 374 exit(0); 375 } 376 usage(1); 377 /* not reached */ 378 return(0); 379 } 380 381 static 382 void 383 hammer_parsedevs(const char *blkdevs) 384 { 385 char *copy; 386 char *volname; 387 388 if (blkdevs == NULL) { 389 errx(1, "A -f blkdev[:blkdev]* specification is required " 390 "for this command"); 391 } 392 393 copy = strdup(blkdevs); 394 while ((volname = copy) != NULL) { 395 if ((copy = strchr(copy, ':')) != NULL) 396 *copy++ = 0; 397 setup_volume(-1, volname, 0, O_RDONLY); 398 } 399 } 400 401 static 402 void 403 sigalrm(int signo __unused) 404 { 405 /* do nothing (interrupts HAMMER ioctl) */ 406 } 407 408 static 409 void 410 sigintr(int signo __unused) 411 { 412 if (RunningIoctl == 0) 413 _exit(1); 414 DidInterrupt = 1; 415 /* do nothing (interrupts HAMMER ioctl) */ 416 } 417 418 static 419 void 420 usage(int exit_code) 421 { 422 fprintf(stderr, 423 "hammer -h\n" 424 "hammer [-2qrvy] [-b bandwidth] [-c cyclefile] [-f blkdev[:blkdev]*]\n" 425 " [-i delay ] [-t seconds] command [argument ...]\n" 426 "hammer synctid <filesystem> [quick]\n" 427 "hammer -f blkdev[:blkdev]* blockmap\n" 428 "hammer bstats [interval]\n" 429 "hammer iostats [interval]\n" 430 "hammer history[@offset[,len]] <file> ...\n" 431 "hammer -f blkdev[:blkdev]* [-r] [-vvv] show [offset]\n" 432 #if 0 433 "hammer -f blkdev[:blkdev]* blockmap\n" 434 #endif 435 "hammer namekey1 <path>\n" 436 "hammer namekey2 <path>\n" 437 "hammer cleanup [<filesystem> ...]\n" 438 "hammer snapshot [<filesystem>] <snapshot-dir>\n" 439 "hammer prune <softlink-dir>\n" 440 "hammer prune-everything <filesystem>\n" 441 "hammer rebalance <filesystem> [saturation_percentage]\n" 442 "hammer reblock[-btree/inodes/dirs/data] " 443 "<filesystem> [fill_percentage]\n" 444 "hammer pfs-status <dirpath> ...\n" 445 "hammer pfs-master <dirpath> [options]\n" 446 "hammer pfs-slave <dirpath> [options]\n" 447 "hammer pfs-update <dirpath> [options]\n" 448 "hammer pfs-upgrade <dirpath>\n" 449 "hammer pfs-downgrade <dirpath>\n" 450 "hammer pfs-destroy <dirpath>\n" 451 "hammer mirror-read <filesystem> [begin-tid]\n" 452 "hammer mirror-read-stream <filesystem> [begin-tid]\n" 453 "hammer mirror-write <filesystem>\n" 454 "hammer mirror-dump\n" 455 "hammer mirror-copy [[user@]host:]<filesystem>" 456 " [[user@]host:]<filesystem>\n" 457 "hammer mirror-stream [[user@]host:]<filesystem>" 458 " [[user@]host:]<filesystem>\n" 459 "hammer version <filesystem>\n" 460 "hammer version-upgrade <filesystem> version# [force]\n" 461 ); 462 exit(exit_code); 463 } 464 465