From 92d9b902db8fbb74fa869b33a55e35e63e2bf558 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Fri, 5 Dec 2003 06:36:15 +0000 Subject: [PATCH] Small xfs_io tweaks and fixes. --- VERSION | 2 +- debian/changelog | 6 +++ doc/CHANGES | 5 +++ io/command.h | 3 +- io/input.c | 99 +++++++++++++++++++++++++++++++++++++++++++++--- io/input.h | 4 ++ io/pread.c | 38 ++++++++++++------- io/pwrite.c | 38 +++++++++++++------ 8 files changed, 163 insertions(+), 32 deletions(-) diff --git a/VERSION b/VERSION index b62db7f4a..b599fbacc 100644 --- a/VERSION +++ b/VERSION @@ -3,5 +3,5 @@ # PKG_MAJOR=2 PKG_MINOR=6 -PKG_REVISION=0 +PKG_REVISION=1 PKG_BUILD=0 diff --git a/debian/changelog b/debian/changelog index abb851c87..6eeca4198 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +xfsprogs (2.6.1-1) unstable; urgency=low + + * New upstream release. + + -- Nathan Scott Thu, 27 Nov 2003 13:47:17 +1100 + xfsprogs (2.6.0-1) unstable; urgency=low * New upstream release. diff --git a/doc/CHANGES b/doc/CHANGES index 86747ad8b..fb803e8c5 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,3 +1,8 @@ +xfsprogs-2.6.1 (27 November 2003) + - Human-friendly xfs_io read/write bsize specifications. + - Dump throughput and IOPs values after xfs_io reads/writes. + - Sync up user/kernel source in libxfs, libxlog and headers. + xfsprogs-2.6.0 (28 October 2003) - Change to mkfs strategy for allocation group count and size default. Scales significantly better for large filesystems. diff --git a/io/command.h b/io/command.h index 69ee12b94..9d291f1db 100644 --- a/io/command.h +++ b/io/command.h @@ -73,4 +73,5 @@ extern int openfile(char *, xfs_fsop_geom_t *, extern void *buffer; extern ssize_t buffersize; extern int alloc_buffer(ssize_t, unsigned int); -extern int read_buffer(int, off64_t, ssize_t, ssize_t *, int, int); +extern int read_buffer(int, off64_t, long long, long long *, + int, int); diff --git a/io/input.c b/io/input.c index 3e0ed5328..817b46666 100644 --- a/io/input.c +++ b/io/input.c @@ -143,6 +143,13 @@ doneline( free(vec); } +#define EXABYTES(x) ((long long)(x) << 60) +#define PETABYTES(x) ((long long)(x) << 50) +#define TERABYTES(x) ((long long)(x) << 40) +#define GIGABYTES(x) ((long long)(x) << 30) +#define MEGABYTES(x) ((long long)(x) << 20) +#define KILOBYTES(x) ((long long)(x) << 10) + long long cvtnum( int blocksize, @@ -163,14 +170,96 @@ cvtnum( if (*sp == 's' && sp[1] == '\0') return i * sectorsize; if (*sp == 'k' && sp[1] == '\0') - return 1024LL * i; + return KILOBYTES(i); if (*sp == 'm' && sp[1] == '\0') - return 1024LL * 1024LL * i; + return MEGABYTES(i); if (*sp == 'g' && sp[1] == '\0') - return 1024LL * 1024LL * 1024LL * i; + return GIGABYTES(i); if (*sp == 't' && sp[1] == '\0') - return 1024LL * 1024LL * 1024LL * 1024LL * i; + return TERABYTES(i); if (*sp == 'p' && sp[1] == '\0') - return 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * i; + return PETABYTES(i); + if (*sp == 'e' && sp[1] == '\0') + return EXABYTES(i); return -1LL; } + +#define TO_EXABYTES(x) ((x) / EXABYTES(1)) +#define TO_PETABYTES(x) ((x) / PETABYTES(1)) +#define TO_TERABYTES(x) ((x) / TERABYTES(1)) +#define TO_GIGABYTES(x) ((x) / GIGABYTES(1)) +#define TO_MEGABYTES(x) ((x) / MEGABYTES(1)) +#define TO_KILOBYTES(x) ((x) / KILOBYTES(1)) + +void +cvtstr( + double value, + char *str, + size_t size) +{ + char *fmt; + int precise; + + precise = ((double)value * 1000 == (double)(int)value * 1000); + + if (value >= EXABYTES(1)) { + fmt = precise ? "%.f EiB" : "%.3f EiB"; + snprintf(str, size, fmt, TO_EXABYTES(value)); + } else if (value >= PETABYTES(1)) { + fmt = precise ? "%.f PiB" : "%.3f PiB"; + snprintf(str, size, fmt, TO_PETABYTES(value)); + } else if (value >= TERABYTES(1)) { + fmt = precise ? "%.f TiB" : "%.3f TiB"; + snprintf(str, size, fmt, TO_TERABYTES(value)); + } else if (value >= GIGABYTES(1)) { + fmt = precise ? "%.f GiB" : "%.3f GiB"; + snprintf(str, size, fmt, TO_GIGABYTES(value)); + } else if (value >= MEGABYTES(1)) { + fmt = precise ? "%.f MiB" : "%.3f MiB"; + snprintf(str, size, fmt, TO_MEGABYTES(value)); + } else if (value >= KILOBYTES(1)) { + fmt = precise ? "%.f KiB" : "%.3f KiB"; + snprintf(str, size, fmt, TO_KILOBYTES(value)); + } else { + snprintf(str, size, "%f bytes", value); + } +} + +struct timeval +tsub(struct timeval t1, struct timeval t2) +{ + t1.tv_usec -= t2.tv_usec; + if (t1.tv_usec < 0) { + t1.tv_usec += 1000000; + t1.tv_sec--; + } + t1.tv_sec -= t2.tv_sec; + return t1; +} + +double +tdiv(double value, struct timeval tv) +{ + return value / ((double)tv.tv_sec + ((double)tv.tv_usec / 1000000.0)); +} + +#define HOURS(sec) ((sec) / (60 * 60)) +#define MINUTES(sec) (((sec) % (60 * 60)) / 60) +#define SECONDS(sec) ((sec) % 60) + +void +timestr( + struct timeval *tv, + char *ts, + size_t size) +{ + if (!tv->tv_sec) + snprintf(ts, size, "%.4f sec", + ((double) tv->tv_usec / 1000000.0)); + else + snprintf(ts, size, "%02u:%02u:%02u.%-u", + (unsigned int) HOURS(tv->tv_sec), + (unsigned int) MINUTES(tv->tv_sec), + (unsigned int) SECONDS(tv->tv_sec), + (unsigned int) tv->tv_usec); +} diff --git a/io/input.h b/io/input.h index 1121dcfb9..d51536217 100644 --- a/io/input.h +++ b/io/input.h @@ -34,4 +34,8 @@ extern char **breakline(char *input, int *count); extern void doneline(char *input, char **vec); extern char *fetchline(void); extern long long cvtnum(int blocksize, int sectorsize, char *s); +extern void cvtstr(double value, char *str, size_t sz); +extern struct timeval tsub(struct timeval t1, struct timeval t2); +extern double tdiv(double value, struct timeval tv); +extern void timestr(struct timeval *tv, char *str, size_t sz); diff --git a/io/pread.c b/io/pread.c index f4eea9a18..579c00967 100644 --- a/io/pread.c +++ b/io/pread.c @@ -106,31 +106,34 @@ int read_buffer( int fd, off64_t offset, - ssize_t count, - ssize_t *total, + long long count, + long long *total, int verbose, int onlyone) { - ssize_t bytes; + ssize_t bytes, bytes_requested; + int ops = 0; *total = 0; while (count > 0) { - bytes = pread64(fd, buffer, min(count,buffersize), offset); + bytes_requested = min(count, buffersize); + bytes = pread64(fd, buffer, bytes_requested, offset); if (bytes == 0) break; if (bytes < 0) { perror("pread64"); - return 0; + return -1; } + ops++; if (verbose) dump_buffer(offset, bytes); *total += bytes; - if (onlyone || bytes < count) + if (onlyone || bytes < bytes_requested) break; offset += bytes; count -= bytes; } - return 1; + return ops; } static int @@ -139,17 +142,18 @@ pread_f( char **argv) { off64_t offset; - ssize_t count, total; + long long count, total; unsigned int bsize = 4096; - char *sp; + struct timeval t1, t2; + char s1[64], s2[64], ts[64]; int vflag = 0; int c; while ((c = getopt(argc, argv, "b:v")) != EOF) { switch (c) { case 'b': - bsize = strtoul(optarg, &sp, 0); - if (!sp || sp == optarg) { + bsize = cvtnum(fgeom.blocksize, fgeom.sectsize, optarg); + if (bsize < 0) { printf(_("non-numeric bsize -- %s\n"), optarg); return 0; } @@ -172,7 +176,7 @@ pread_f( return 0; } optind++; - count = (ssize_t)cvtnum(fgeom.blocksize, fgeom.sectsize, argv[optind]); + count = cvtnum(fgeom.blocksize, fgeom.sectsize, argv[optind]); if (count < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; @@ -181,11 +185,19 @@ pread_f( if (!alloc_buffer(bsize, 0xabababab)) return 0; - if (!read_buffer(fdesc, offset, count, &total, vflag, 0)) + gettimeofday(&t1, NULL); + if ((c = read_buffer(fdesc, offset, count, &total, vflag, 0)) < 0) return 0; + gettimeofday(&t2, NULL); + t2 = tsub(t2, t1); printf(_("read %ld/%ld bytes at offset %lld\n"), (long)total, (long)count, (long long)offset); + cvtstr((double)total, s1, sizeof(s1)); + cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); + timestr(&t2, ts, sizeof(ts)); + printf(_("---- %s, %d ops; %s (%s/sec and %.f ops/sec)\n"), + s1, c, ts, s2, tdiv((double)c, t2)); return 0; } diff --git a/io/pwrite.c b/io/pwrite.c index 6d4079e72..5848611f7 100644 --- a/io/pwrite.c +++ b/io/pwrite.c @@ -61,35 +61,38 @@ pwrite_help(void) static int write_buffer( off64_t offset, - ssize_t count, + long long count, ssize_t bs, int fd, off64_t skip, - ssize_t *total) + long long *total) { - ssize_t bytes, bytes_requested, itotal = min(bs, count); + ssize_t bytes, bytes_requested; + long long bar = min(bs, count); + int ops = 0; *total = 0; while (count > 0) { if (fd > 0) { /* input file given, read buffer first */ - if (!read_buffer(fd, skip + *total, bs, &itotal, 0, 1)) + if (read_buffer(fd, skip + *total, bs, &bar, 0, 1) < 0) break; } - bytes_requested = min(itotal, count); + bytes_requested = min(bar, count); bytes = pwrite64(fdesc, buffer, bytes_requested, offset); if (bytes == 0) break; if (bytes < 0) { perror("pwrite64"); - return 0; + return -1; } + ops++; *total += bytes; if (bytes < bytes_requested) break; offset += bytes; count -= bytes; } - return 1; + return ops; } static int @@ -98,17 +101,19 @@ pwrite_f( char **argv) { off64_t offset, skip = 0; - ssize_t count, total; + long long count, total; unsigned int seed = 0xcdcdcdcd; unsigned int bsize = 4096; + struct timeval t1, t2; + char s1[64], s2[64], ts[64]; char *sp, *infile = NULL; int c, fd = -1, dflag = 0; while ((c = getopt(argc, argv, "b:df:i:s:S:")) != EOF) { switch (c) { case 'b': - bsize = strtoul(optarg, &sp, 0); - if (!sp || sp == optarg) { + bsize = cvtnum(fgeom.blocksize, fgeom.sectsize, optarg); + if (bsize < 0) { printf(_("non-numeric bsize -- %s\n"), optarg); return 0; } @@ -149,7 +154,7 @@ pwrite_f( return 0; } optind++; - count = (ssize_t)cvtnum(fgeom.blocksize, fgeom.sectsize, argv[optind]); + count = cvtnum(fgeom.blocksize, fgeom.sectsize, argv[optind]); if (count < 0) { printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; @@ -162,12 +167,21 @@ pwrite_f( ((fd = openfile(infile, NULL, 0, 0, dflag, 1, 0, 0, 0)) < 0)) return 0; - if (!write_buffer(offset, count, bsize, fd, skip, &total)) { + gettimeofday(&t1, NULL); + if ((c = write_buffer(offset, count, bsize, fd, skip, &total)) < 0) { close(fd); return 0; } + gettimeofday(&t2, NULL); + t2 = tsub(t2, t1); + printf(_("wrote %ld/%ld bytes at offset %lld\n"), (long)total, (long)count, (long long)offset); + cvtstr((double)total, s1, sizeof(s1)); + cvtstr(tdiv((double)total, t2), s2, sizeof(s2)); + timestr(&t2, ts, sizeof(ts)); + printf(_("----- %s, %d ops; %s (%s/sec and %.f ops/sec)\n"), + s1, c, ts, s2, tdiv((double)c, t2)); close(fd); return 0; } -- 2.47.2