From: Matthew Dillon Date: Sun, 4 May 2008 19:18:17 +0000 (+0000) Subject: HAMMER Utilities: enhanced show, timeout option X-Git-Tag: v2.0.1~710 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/0006adae7fd20cb2dd99f0f580cd81d285d56352 HAMMER Utilities: enhanced show, timeout option * Enchange the show command when used with -vvv. The command now reports directory entries and basic information about inodes. * Add the [-t timeout] option. The idea is to use this to limit the amount of time hammer spends reblocking or pruning a filesystem when running the command from a cron job. * Adjust the format of the softlink option to be more consistent. --- diff --git a/sbin/hammer/cmd_prune.c b/sbin/hammer/cmd_prune.c index fa5a233641..ac4199bc2f 100644 --- a/sbin/hammer/cmd_prune.c +++ b/sbin/hammer/cmd_prune.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/Attic/cmd_prune.c,v 1.4 2008/03/20 04:03:03 dillon Exp $ + * $DragonFly: src/sbin/hammer/Attic/cmd_prune.c,v 1.5 2008/05/04 19:18:17 dillon Exp $ */ #include "hammer.h" @@ -93,10 +93,16 @@ hammer_cmd_prune(char **av, int ac) fd = open(filesystem, O_RDONLY); if (fd < 0) err(1, "Unable to open %s", filesystem); - if (ioctl(fd, HAMMERIOC_PRUNE, &prune) < 0) - printf("Prune %s failed: %s\n", filesystem, strerror(errno)); - else + if (ioctl(fd, HAMMERIOC_PRUNE, &prune) < 0) { + if (errno == EINTR) { + printf("Prune %s interrupted by timer\n", filesystem); + } else { + printf("Prune %s failed: %s\n", + filesystem, strerror(errno)); + } + } else { printf("Prune %s succeeded\n", filesystem); + } close(fd); if (LinkPath) hammer_prune_create_links(filesystem, &prune); @@ -311,7 +317,7 @@ hammer_prune_make_softlink(const char *filesystem, hammer_tid_t tid) if (tid % (1000000000ULL * 60 * 60 * 24) == 0) { strftime(buf, sizeof(buf), "snap-%d%b%Y", tp); } else if (tid % (1000000000ULL * 60 * 60) == 0) { - strftime(buf, sizeof(buf), "snap-%d%b%Y_%H", tp); + strftime(buf, sizeof(buf), "snap-%d%b%Y_%H%M", tp); } else if (tid % (1000000000ULL * 60) == 0) { strftime(buf, sizeof(buf), "snap-%d%b%Y_%H%M", tp); } else { diff --git a/sbin/hammer/cmd_reblock.c b/sbin/hammer/cmd_reblock.c index 97ce0f586b..c396c0a5b4 100644 --- a/sbin/hammer/cmd_reblock.c +++ b/sbin/hammer/cmd_reblock.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_reblock.c,v 1.1 2008/03/18 05:21:53 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_reblock.c,v 1.2 2008/05/04 19:18:17 dillon Exp $ */ #include "hammer.h" @@ -73,10 +73,16 @@ hammer_cmd_reblock(char **av, int ac) fd = open(filesystem, O_RDONLY); if (fd < 0) err(1, "Unable to open %s", filesystem); - if (ioctl(fd, HAMMERIOC_REBLOCK, &reblock) < 0) - printf("Reblock %s failed: %s\n", filesystem, strerror(errno)); - else + if (ioctl(fd, HAMMERIOC_REBLOCK, &reblock) < 0) { + if (errno == EINTR) { + printf("Reblock %s interrupted by timer\n", filesystem); + } else { + printf("Reblock %s failed: %s\n", + filesystem, strerror(errno)); + } + } else { printf("Reblock %s succeeded\n", filesystem); + } close(fd); printf("Reblocked:\n" " %lld/%lld btree nodes\n" diff --git a/sbin/hammer/cmd_show.c b/sbin/hammer/cmd_show.c index dceb480abc..9528e7d166 100644 --- a/sbin/hammer/cmd_show.c +++ b/sbin/hammer/cmd_show.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_show.c,v 1.6 2008/02/23 03:01:06 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_show.c,v 1.7 2008/05/04 19:18:17 dillon Exp $ */ #include "hammer.h" @@ -39,16 +39,19 @@ #define FLAG_TOOFARLEFT 0x0001 #define FLAG_TOOFARRIGHT 0x0002 #define FLAG_BADTYPE 0x0004 +#define FLAG_BADCHILDPARENT 0x0008 static void print_btree_node(hammer_off_t node_offset, int depth, int spike, hammer_base_elm_t left_bound, hammer_base_elm_t right_bound); static void print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, int flags, const char *label); -static int print_elm_flags(hammer_node_ondisk_t node, hammer_btree_elm_t elm, - u_int8_t btype, hammer_base_elm_t left_bound, +static int print_elm_flags(hammer_node_ondisk_t node, hammer_off_t node_offset, + hammer_btree_elm_t elm, u_int8_t btype, + hammer_base_elm_t left_bound, hammer_base_elm_t right_bound); static void print_bigblock_fill(hammer_off_t offset); +static void print_record(hammer_btree_elm_t elm); void hammer_cmd_show(hammer_off_t node_offset, int depth, @@ -93,13 +96,15 @@ print_btree_node(hammer_off_t node_offset, int depth, int spike, for (i = 0; i < node->count; ++i) { elm = &node->elms[i]; - flags = print_elm_flags(node, elm, elm->base.btype, + flags = print_elm_flags(node, node_offset, + elm, elm->base.btype, left_bound, right_bound); print_btree_elm(elm, i, node->type, flags, "ELM"); } if (node->type == HAMMER_BTREE_TYPE_INTERNAL) { elm = &node->elms[i]; - flags = print_elm_flags(node, elm, 'I', + flags = print_elm_flags(node, node_offset, + elm, 'I', left_bound, right_bound); print_btree_elm(elm, i, node->type, flags, "RBN"); } @@ -138,6 +143,8 @@ print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, flagstr[3] = 'R'; if (flags & FLAG_BADTYPE) flagstr[4] = 'T'; + if (flags & FLAG_BADCHILDPARENT) + flagstr[4] = 'C'; printf("%s\t%s %2d %c ", flagstr, label, i, @@ -147,7 +154,8 @@ print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, elm->base.key, elm->base.rec_type, elm->base.obj_type); - printf("\t tids %016llx:%016llx ", + printf("\t %c tids %016llx:%016llx ", + (elm->base.delete_tid ? 'd' : ' '), elm->base.create_tid, elm->base.delete_tid); @@ -168,6 +176,8 @@ print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, printf(", "); print_bigblock_fill(elm->leaf.data_offset); } + if (VerboseOpt > 1) + print_record(elm); break; } break; @@ -179,14 +189,25 @@ print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, static int -print_elm_flags(hammer_node_ondisk_t node, hammer_btree_elm_t elm, - u_int8_t btype, +print_elm_flags(hammer_node_ondisk_t node, hammer_off_t node_offset, + hammer_btree_elm_t elm, u_int8_t btype, hammer_base_elm_t left_bound, hammer_base_elm_t right_bound) { int flags = 0; switch(node->type) { case HAMMER_BTREE_TYPE_INTERNAL: + if (elm->internal.subtree_offset) { + struct buffer_info *buffer = NULL; + hammer_node_ondisk_t subnode; + + subnode = get_node(elm->internal.subtree_offset, + &buffer); + if (subnode->parent != node_offset) + flags |= FLAG_BADCHILDPARENT; + rel_buffer(buffer); + } + switch(btype) { case HAMMER_BTREE_TYPE_INTERNAL: if (left_bound == NULL || right_bound == NULL) @@ -250,3 +271,60 @@ print_bigblock_fill(hammer_off_t offset) ); } +static +void +print_record(hammer_btree_elm_t elm) +{ + struct buffer_info *rec_buffer; + struct buffer_info *data_buffer; + hammer_record_ondisk_t rec; + hammer_off_t rec_offset; + hammer_off_t data_offset; + int32_t data_len; + char *data; + + rec_offset = elm->leaf.rec_offset; + data_offset = elm->leaf.data_offset; + data_len = elm->leaf.data_len; + rec_buffer = NULL; + data_buffer = NULL; + + rec = get_buffer_data(rec_offset, &rec_buffer, 0); + if (data_offset) + data = get_buffer_data(data_offset, &data_buffer, 0); + else + data = NULL; + + printf("\n%17s", ""); + if (rec == NULL) { + printf("record FAILED\n"); + return; + } + switch(rec->base.base.rec_type) { + case HAMMER_RECTYPE_INODE: + printf("size=%lld nlinks=%lld", + rec->inode.ino_size, rec->inode.ino_nlinks); + break; + case HAMMER_RECTYPE_DIRENTRY: + printf("dir-entry ino=%016llx name=\"%*.*s\"", + rec->entry.obj_id, + data_len, data_len, data); + break; + case HAMMER_RECTYPE_FIX: + switch(rec->base.base.key) { + case HAMMER_FIXKEY_SYMLINK: + printf("symlink=\"%*.*s\"", data_len, data_len, data); + break; + default: + break; + } + break; + default: + break; + } + if (rec_buffer) + rel_buffer(rec_buffer); + if (data_buffer) + rel_buffer(data_buffer); +} + diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 8d3f488069..e08dedad7c 100644 --- a/sbin/hammer/hammer.8 +++ b/sbin/hammer/hammer.8 @@ -30,7 +30,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.11 2008/04/14 08:17:09 swildner Exp $ +.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.12 2008/05/04 19:18:17 dillon Exp $ .Dd December 31, 2007 .Dt HAMMER 8 .Os @@ -42,6 +42,7 @@ .Op Fl hrx .Op Fl f Ar blkdev[:blkdev]* .Op Fl s Ar linkpath +.Op Fl t Ar timeout .Ar command .Ar ... .Sh DESCRIPTION @@ -61,6 +62,10 @@ Specify the volumes making up a HAMMER filesystem. .It Fl s Ar linkpath When pruning a filesystem you can instruct HAMMER to create softlinks to available snapshots. +.It Fl t Ar timeout +When pruning and reblocking you can tell the utility to stop after a +certain period of time. +This option is typically used to limit the time spent reblocking. .It Fl v Increase verboseness. May be specified multiple times. .It Fl x diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index c931aa501e..49db592421 100644 --- a/sbin/hammer/hammer.c +++ b/sbin/hammer/hammer.c @@ -31,15 +31,17 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/hammer.c,v 1.13 2008/03/25 03:57:58 dillon Exp $ + * $DragonFly: src/sbin/hammer/hammer.c,v 1.14 2008/05/04 19:18:17 dillon Exp $ */ #include "hammer.h" +#include #include static void hammer_parsetime(u_int64_t *tidp, const char *timestr); static void hammer_waitsync(int dosleep); static void hammer_parsedevs(const char *blkdevs); +static void sigalrm(int signo); static void usage(int exit_code); int RecurseOpt; @@ -53,10 +55,11 @@ main(int ac, char **av) struct timeval tv; u_int64_t tid; int ch; + int timeout = 0; u_int32_t status; char *blkdevs = NULL; - while ((ch = getopt(ac, av, "hf:rs:vx")) != -1) { + while ((ch = getopt(ac, av, "hf:rs:t:vx")) != -1) { switch(ch) { case 'h': usage(0); @@ -70,6 +73,9 @@ main(int ac, char **av) case 's': LinkPath = optarg; break; + case 't': + timeout = strtol(optarg, NULL, 0); + break; case 'v': ++VerboseOpt; break; @@ -88,6 +94,11 @@ main(int ac, char **av) /* not reached */ } + if (timeout > 0) { + signal(SIGALRM, sigalrm); + alarm(timeout); + } + if (strcmp(av[0], "now") == 0) { hammer_waitsync(1); tid = (hammer_tid_t)time(NULL) * 1000000000LLU; @@ -290,6 +301,13 @@ hammer_parsedevs(const char *blkdevs) } } +static +void +sigalrm(int signo __unused) +{ + /* do nothing (interrupts HAMMER ioctl) */ +} + static void usage(int exit_code)