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