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