From 002d955f56f4771ca6bd0b94da961c10bfe0a597 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 25 Mar 2008 03:57:58 +0000 Subject: [PATCH] HAMMER utilities: automatic sync/sleep * Add 64 bit versions of the 'now' and 'stamp' commands, called 'now64' and 'stamp64'. * The 'now' and 'now64' commands now automatically sync. * The 'now' command also sleeps until the second hand turns over. * Add a new option, -x, which may be used to disable the automatic sync & sleep. The stamp and stamp64 commands do not sync or sleep. Suggested-by: "Thomas E. Spanjaard" --- sbin/hammer/hammer.8 | 25 ++++++++++++++++-- sbin/hammer/hammer.c | 74 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 487bdc999..e03cf3b66 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.8 2008/03/20 04:03:03 dillon Exp $ +.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.9 2008/03/25 03:57:58 dillon Exp $ .Dd December 31, 2007 .Dt HAMMER 8 .Os @@ -39,7 +39,7 @@ .Nd HAMMER file system utility .Sh SYNOPSIS .Nm -.Op Fl hr +.Op Fl hrx .Op Fl f Ar blkdev[:blkdev]* .Op Fl s Ar linkpath .Ar command @@ -63,6 +63,10 @@ When pruning a filesystem you can instruct HAMMER to create softlinks to available snapshots. .It Fl v Increase verboseness. May be specified multiple times. +.It Fl x +Do not call sync() when running commands which sync() by default. +Timestamp commands such as 'hammer now' sync() by default. This also +disables any sleeps the timestamp commands would otherwise perform. .El .Pp The commands are as follows: @@ -70,14 +74,31 @@ The commands are as follows: .It Ar now Generate a timestamp suitable for use in the @@ filename extension, representing right now. +Unless +.Fl x +is specified, this command will automatically sync() and +wait for the seconds hand to turn over (sleep for up to one second) prior +to generating a seconds-denominated timestamp. +.It Ar now64 +Generate a full 64 bit timestamp. +Unless +.Fl x +is specified, this command will automatically sync(), but not sleep, +prior to generating the timestamp. .It Ar stamp Generate a timestamp suitable for use in the @@ filename extension. +This command does not sync() or sleep and care should be taken if +generating timestamps for data which may not yet be synced to disk. A time specification of .Pf yyyymmdd Oo :hhmmss Oc Ns Op .fractional specifies an exact as-of timestamp in local (not UTC) time. Set the TZ environment variable prior to running .Nm if you wish to specify the time by some other means. +.It Ar stamp64 +Same as the +.Ar stamp +command but generates a 64 bit timestamp. .It Ar history Ar path Show the modification history for a HAMMER file's inode and data. .It Ar show Op vol_no[:clu_no] diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index 120c6f3d6..c931aa501 100644 --- a/sbin/hammer/hammer.c +++ b/sbin/hammer/hammer.c @@ -31,28 +31,32 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/hammer.c,v 1.12 2008/03/20 04:03:03 dillon Exp $ + * $DragonFly: src/sbin/hammer/hammer.c,v 1.13 2008/03/25 03:57:58 dillon Exp $ */ #include "hammer.h" +#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 usage(int exit_code); int RecurseOpt; int VerboseOpt; +int NoSyncOpt; const char *LinkPath; int main(int ac, char **av) { + struct timeval tv; u_int64_t tid; int ch; u_int32_t status; char *blkdevs = NULL; - while ((ch = getopt(ac, av, "hf:rs:v")) != -1) { + while ((ch = getopt(ac, av, "hf:rs:vx")) != -1) { switch(ch) { case 'h': usage(0); @@ -69,6 +73,9 @@ main(int ac, char **av) case 'v': ++VerboseOpt; break; + case 'x': + ++NoSyncOpt; + break; default: usage(1); /* not reached */ @@ -82,10 +89,19 @@ main(int ac, char **av) } if (strcmp(av[0], "now") == 0) { - hammer_parsetime(&tid, "0s"); + hammer_waitsync(1); + tid = (hammer_tid_t)time(NULL) * 1000000000LLU; printf("0x%08x\n", (int)(tid / 1000000000LL)); exit(0); } + if (strcmp(av[0], "now64") == 0) { + hammer_waitsync(0); + gettimeofday(&tv, NULL); + tid = (hammer_tid_t)tv.tv_sec * 1000000000LLU + + tv.tv_usec * 1000LLU; + printf("0x%016llx\n", tid); + exit(0); + } if (strcmp(av[0], "stamp") == 0) { if (av[1] == NULL) usage(1); @@ -93,6 +109,13 @@ main(int ac, char **av) printf("0x%08x\n", (int)(tid / 1000000000LL)); exit(0); } + if (strcmp(av[0], "stamp64") == 0) { + if (av[1] == NULL) + usage(1); + hammer_parsetime(&tid, av[1]); + printf("0x%016llx\n", tid); + exit(0); + } if (strcmp(av[0], "namekey") == 0) { int64_t key; @@ -164,13 +187,12 @@ static void hammer_parsetime(u_int64_t *tidp, const char *timestr) { + struct timeval tv; struct tm tm; - time_t t; int32_t n; char c; - double seconds = 0; - t = time(NULL); + gettimeofday(&tv, NULL); if (*timestr == 0) usage(1); @@ -196,13 +218,15 @@ hammer_parsetime(u_int64_t *tidp, const char *timestr) n *= 60; /* fall through */ case 's': - t -= n; + tv.tv_sec -= n; break; default: usage(1); } } else { - localtime_r(&t, &tm); + double seconds = 0; + + localtime_r(&tv.tv_sec, &tm); seconds = (double)tm.tm_sec; tm.tm_year += 1900; tm.tm_mon += 1; @@ -216,10 +240,34 @@ hammer_parsetime(u_int64_t *tidp, const char *timestr) tm.tm_hour = tm.tm_min = tm.tm_sec = 0; else tm.tm_sec = (int)seconds; - t = mktime(&tm); + tv.tv_sec = mktime(&tm); + tv.tv_usec = (int)((seconds - floor(seconds)) * 1000000.0); + } + *tidp = (u_int64_t)tv.tv_sec * 1000000000LLU + + tv.tv_usec * 1000LLU; +} + +/* + * If the TID is within 60 seconds of the current time we sync(). If + * dosleep is non-zero and the TID is within 1 second of the current time + * we wait for the second-hand to turn over. + * + * The NoSyncOpt prevents both the sync() call and any sleeps from occuring. + */ +static +void +hammer_waitsync(int dosleep) +{ + time_t t1, t2; + + if (NoSyncOpt == 0) { + sync(); + t1 = t2 = time(NULL); + while (dosleep && t1 == t2) { + usleep(100000); + t2 = time(NULL); + } } - *tidp = (u_int64_t)t * 1000000000 + - (seconds - (int)seconds) * 1000000000; } static @@ -248,8 +296,8 @@ usage(int exit_code) { fprintf(stderr, "hammer -h\n" - "hammer now\n" - "hammer stamp