HAMMER - Implement volume-list command
[dragonfly.git] / sbin / hammer / hammer.c
index fa127c8..88b51c4 100644 (file)
@@ -37,6 +37,7 @@
 #include "hammer.h"
 #include <signal.h>
 #include <math.h>
+#include <fstab.h>
 
 static void hammer_parsedevs(const char *blkdevs);
 static void sigalrm(int signo);
@@ -50,10 +51,15 @@ int NoSyncOpt;
 int TwoWayPipeOpt;
 int TimeoutOpt;
 int DelayOpt = 5;
+char *SshPort;
 int ForceYesOpt = 0;
+int CompressOpt;
+int ForceOpt;
 int RunningIoctl;
 int DidInterrupt;
+int BulkOpt;
 u_int64_t BandwidthOpt;
+u_int64_t SplitupOpt = 4ULL * 1024ULL * 1024ULL * 1024ULL;
 const char *CyclePath;
 const char *LinkPath;
 
@@ -64,8 +70,9 @@ main(int ac, char **av)
        char *ptr;
        u_int32_t status;
        int ch;
+       int cacheSize = 0;
 
-       while ((ch = getopt(ac, av, "b:c:dhf:i:qrs:t:v2y")) != -1) {
+       while ((ch = getopt(ac, av, "b:c:dhf:i:p:qrs:t:v2yBC:FS:X")) != -1) {
                switch(ch) {
                case '2':
                        TwoWayPipeOpt = 1;
@@ -95,6 +102,28 @@ main(int ac, char **av)
                                usage(1);
                        }
                        break;
+               case 'S':
+                       SplitupOpt = strtoull(optarg, &ptr, 0);
+                       switch(*ptr) {
+                       case 'g':
+                       case 'G':
+                               SplitupOpt *= 1024;
+                               /* fall through */
+                       case 'm':
+                       case 'M':
+                               SplitupOpt *= 1024;
+                               /* fall through */
+                       case 'k':
+                       case 'K':
+                               SplitupOpt *= 1024;
+                               break;
+                       case '\0':
+                               /* bytes per second if no suffix */
+                               break;
+                       default:
+                               usage(1);
+                       }
+                       break;
                case 'c':
                        CyclePath = optarg;
                        break;
@@ -107,6 +136,9 @@ main(int ac, char **av)
                case 'i':
                        DelayOpt = strtol(optarg, NULL, 0);
                        break;
+               case 'p':
+                       SshPort = optarg;
+                       break;
                case 'r':
                        RecurseOpt = 1;
                        break;
@@ -131,6 +163,48 @@ main(int ac, char **av)
                        else
                                ++QuietOpt;
                        break;
+               case 'B':
+                       BulkOpt = 1;
+                       break;
+               case 'C':
+                       cacheSize = strtol(optarg, &ptr, 0);
+                       switch(*ptr) {
+                       case 'm':
+                       case 'M':
+                               cacheSize *= 1024;
+                               /* fall through */
+                       case 'k':
+                       case 'K':
+                               cacheSize *= 1024;
+                               ++ptr;
+                               break;
+                       case '\0':
+                       case ':':
+                               /* bytes if no suffix */
+                               break;
+                       default:
+                               usage(1);
+                       }
+                       if (*ptr == ':') {
+                               UseReadAhead = strtol(ptr + 1, NULL, 0);
+                               UseReadBehind = -UseReadAhead;
+                       }
+                       if (cacheSize < 1024 * 1024)
+                               cacheSize = 1024 * 1024;
+                       if (UseReadAhead < 0)
+                               usage(1);
+                       if (UseReadAhead * HAMMER_BUFSIZE / cacheSize / 16) {
+                               UseReadAhead = cacheSize / 16 / HAMMER_BUFSIZE;
+                               UseReadBehind = -UseReadAhead;
+                       }
+                       hammer_cache_set(cacheSize);
+                       break;
+               case 'F':
+                       ForceOpt = 1;
+                       break;
+               case 'X':
+                       CompressOpt = 1;
+                       break;
                default:
                        usage(1);
                        /* not reached */
@@ -186,7 +260,7 @@ main(int ac, char **av)
                }
                if (key == 0)
                        key |= 0x100000000LL;
-               printf("0x%016llx\n", key);
+               printf("0x%016jx\n", (uintmax_t)key);
                exit(0);
        }
        if (strcmp(av[0], "namekey1") == 0) {
@@ -197,7 +271,7 @@ main(int ac, char **av)
                key = (int64_t)(crc32(av[1], strlen(av[1])) & 0x7FFFFFFF) << 32;
                if (key == 0)
                        key |= 0x100000000LL;
-               printf("0x%016llx\n", key);
+               printf("0x%016jx\n", (uintmax_t)key);
                exit(0);
        }
        if (strcmp(av[0], "namekey32") == 0) {
@@ -247,14 +321,46 @@ main(int ac, char **av)
                hammer_cmd_softprune(av + 1, ac - 1, 0);
                exit(0);
        }
+       if (strcmp(av[0], "config") == 0) {
+               hammer_cmd_config(av + 1, ac - 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "viconfig") == 0) {
+               hammer_cmd_viconfig(av + 1, ac - 1);
+               exit(0);
+       }
        if (strcmp(av[0], "cleanup") == 0) {
                hammer_cmd_cleanup(av + 1, ac - 1);
                exit(0);
        }
+       if (strcmp(av[0], "info") == 0) {
+               hammer_cmd_info();
+               exit(0);
+       }
        if (strcmp(av[0], "prune-everything") == 0) {
                hammer_cmd_softprune(av + 1, ac - 1, 1);
                exit(0);
        }
+       if (strcmp(av[0], "snap") == 0) {
+               hammer_cmd_snap(av + 1, ac - 1, 0, 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "snaplo") == 0) {
+               hammer_cmd_snap(av + 1, ac - 1, 0, 0);
+               exit(0);
+       }
+       if (strcmp(av[0], "snapq") == 0) {
+               hammer_cmd_snap(av + 1, ac - 1, 1, 0);
+               exit(0);
+       }
+       if (strcmp(av[0], "snapls") == 0) {
+               hammer_cmd_snapls(av + 1, ac - 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "snaprm") == 0) {
+               hammer_cmd_snaprm(av + 1, ac - 1);
+               exit(0);
+       }
        if (strcmp(av[0], "snapshot") == 0) {
                hammer_cmd_snapshot(av + 1, ac - 1);
                exit(0);
@@ -310,6 +416,14 @@ main(int ac, char **av)
                        usage(1);
                exit(0);
        }
+       if (strcmp(av[0], "dedup-simulate") == 0) {
+               hammer_cmd_dedup_simulate(av + 1, ac - 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "dedup") == 0) {
+               hammer_cmd_dedup(av + 1, ac - 1);
+               exit(0);
+       }
        if (strcmp(av[0], "version") == 0) {
                hammer_cmd_get_version(av + 1, ac - 1);
                exit(0);
@@ -318,6 +432,18 @@ main(int ac, char **av)
                hammer_cmd_set_version(av + 1, ac - 1);
                exit(0);
        }
+       if (strcmp(av[0], "volume-add") == 0) {
+               hammer_cmd_volume_add(av + 1, ac - 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "volume-del") == 0) {
+               hammer_cmd_volume_del(av + 1, ac - 1);
+               exit(0);
+       }
+       if (strcmp(av[0], "volume-list") == 0) {
+               hammer_cmd_volume_list(av + 1, ac - 1);
+               exit(0);
+       }
 
        uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status);
        if (status != uuid_s_ok) {
@@ -326,12 +452,25 @@ main(int ac, char **av)
        }
 
        if (strcmp(av[0], "show") == 0) {
-               hammer_off_t node_offset = (hammer_off_t)-1;
+               u_int32_t lo = 0;
+               intmax_t obj_id = (int64_t)HAMMER_MIN_OBJID;
 
                hammer_parsedevs(blkdevs);
                if (ac > 1)
-                       sscanf(av[1], "%llx", &node_offset);
-               hammer_cmd_show(node_offset, 0, NULL, NULL);
+                       sscanf(av[1], "%08x:%jx", &lo, &obj_id);
+               hammer_cmd_show(-1, lo, (int64_t)obj_id, 0, NULL, NULL);
+               exit(0);
+       }
+       if (strcmp(av[0], "show-undo") == 0) {
+               hammer_parsedevs(blkdevs);
+               hammer_cmd_show_undo();
+               exit(0);
+       }
+       if (strcmp(av[0], "recover") == 0) {
+               hammer_parsedevs(blkdevs);
+               if (ac <= 1)
+                       errx(1, "hammer recover required target directory");
+               hammer_cmd_recover(av[1]);
                exit(0);
        }
        if (strcmp(av[0], "blockmap") == 0) {
@@ -339,11 +478,24 @@ main(int ac, char **av)
                hammer_cmd_blockmap();
                exit(0);
        }
+       if (strcmp(av[0], "checkmap") == 0) {
+               hammer_parsedevs(blkdevs);
+               hammer_cmd_checkmap();
+               exit(0);
+       }
        usage(1);
        /* not reached */
        return(0);
 }
 
+/*
+ * Parse the device specification.
+ *
+ * Multi-volume hammer devices are colon-separated.  Each element
+ * may be further expanded via /etc/devtab.  One may also specify
+ * a single element which is expanded into multiple elements via
+ * /etc/devtab.
+ */
 static
 void
 hammer_parsedevs(const char *blkdevs)
@@ -352,7 +504,7 @@ hammer_parsedevs(const char *blkdevs)
        char *volname;
 
        if (blkdevs == NULL) {
-               errx(1, "A -f blkdev[:blkdev]* specification is required "
+               errx(1, "A -f blkdevs specification is required "
                        "for this command");
        }
 
@@ -360,7 +512,11 @@ hammer_parsedevs(const char *blkdevs)
        while ((volname = copy) != NULL) {
                if ((copy = strchr(copy, ':')) != NULL)
                        *copy++ = 0;
-               setup_volume(-1, volname, 0, O_RDONLY);
+               volname = getdevpath(volname, 0);
+               if (strchr(volname, ':'))
+                       hammer_parsedevs(volname);
+               else
+                       setup_volume(-1, volname, 0, O_RDONLY);
        }
 }
 
@@ -387,25 +543,24 @@ usage(int exit_code)
 {
        fprintf(stderr, 
                "hammer -h\n"
-               "hammer [-2qrvy] [-b bandwidth] [-c cyclefile] [-f blkdev[:blkdev]*]\n"
-               "       [-i delay ] [-t seconds] command [argument ...]\n"
+               "hammer [-2BqrvXy] [-b bandwidth] [-C cachesize[:readahead]] [-c cyclefile]\n"
+               "       [-f blkdevs] [-i delay] [-t seconds] [-S splitup]\n"
+               "       command [argument ...]\n"
                "hammer synctid <filesystem> [quick]\n"
-               "hammer -f blkdev[:blkdev]* blockmap\n"
                "hammer bstats [interval]\n"
                "hammer iostats [interval]\n"
                "hammer history[@offset[,len]] <file> ...\n"
-               "hammer -f blkdev[:blkdev]* [-r] [-vvv] show [offset]\n"
-#if 0
-               "hammer -f blkdev[:blkdev]* blockmap\n"
-#endif
                "hammer namekey1 <path>\n"
                "hammer namekey2 <path>\n"
+               "hammer namekey32 <path>\n"
                "hammer cleanup [<filesystem> ...]\n"
+               "hammer info\n"
                "hammer snapshot [<filesystem>] <snapshot-dir>\n"
+               "hammer snapshot <filesystem> <snapshot-dir> [<note>]\n"
                "hammer prune <softlink-dir>\n"
                "hammer prune-everything <filesystem>\n"
                "hammer rebalance <filesystem> [saturation_percentage]\n"
-               "hammer reblock[-btree/inodes/dirs/data] "
+               "hammer reblock[-btree|-inodes|-dirs|-data] "
                        "<filesystem> [fill_percentage]\n"
                "hammer pfs-status <dirpath> ...\n"
                "hammer pfs-master <dirpath> [options]\n"
@@ -423,8 +578,43 @@ usage(int exit_code)
                "hammer mirror-stream [[user@]host:]<filesystem>"
                                    " [[user@]host:]<filesystem>\n"
                "hammer version <filesystem>\n"
-               "hammer version-upgrade <filesystem> version# [force]\n"
+               "hammer version-upgrade <filesystem> <version> [force]\n"
+               "hammer volume-add <device> <filesystem>\n"
+               "hammer volume-del <device> <filesystem>\n"
+               "hammer volume-list <filesystem>\n"
        );
+
+       fprintf(stderr, "\nHAMMER utility version 3+ commands:\n");
+
+       fprintf(stderr,
+               "hammer config [<filesystem> [<configfile>]]\n"
+               "hammer viconfig [<filesystem>]\n"
+               "hammer snap <path> [<note>]\n"
+               "hammer snaplo <path> [<note>]\n"
+               "hammer snapq <dir> [<note>]\n"
+               "hammer snaprm <path> ...\n"
+               "hammer snaprm <transid> ...\n"
+               "hammer snaprm <filesystem> <transid> ...\n"
+               "hammer snapls [<path> ...]\n"
+       );
+
+       fprintf(stderr, "\nHAMMER utility version 4+ commands:\n");
+
+       fprintf(stderr,
+               "hammer -f blkdevs blockmap\n"
+               "hammer -f blkdevs checkmap\n"
+               "hammer -f blkdevs [-qqq] show [lo:objid]\n"
+               "hammer -f blkdevs show-undo\n"
+               "hammer -f blkdevs recover <target_dir>\n"
+       );
+
+       fprintf(stderr, "\nHAMMER utility version 5+ commands:\n");
+
+       fprintf(stderr,
+               "hammer dedup-simulate <filesystem>\n"
+               "hammer dedup <filesystem>\n"
+       );
+
        exit(exit_code);
 }