From d347f827aa921dc68a37bac4c460b48ec62f7525 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Mon, 5 Dec 2005 05:02:42 +0000 Subject: [PATCH] Add xfs_io code to grok direct IO size/alignment information. Merge of master-melb:xfs-cmds:24688a by kenmcd. --- Makefile | 2 +- VERSION | 2 +- debian/changelog | 6 + doc/CHANGES | 5 + io/Makefile | 3 +- io/io.h | 1 + io/open.c | 21 +++- io/pread.c | 44 +++++++- io/pwrite.c | 20 ++-- io/sendfile.c | 12 +- io/xfs_mkfile.sh | 53 +++++++++ libxcmd/input.c | 23 ++-- mkfile/Makefile | 19 ---- mkfile/xfs_mkfile.c | 270 -------------------------------------------- 14 files changed, 163 insertions(+), 318 deletions(-) create mode 100755 io/xfs_mkfile.sh delete mode 100644 mkfile/Makefile delete mode 100644 mkfile/xfs_mkfile.c diff --git a/Makefile b/Makefile index b1ed2581a..055030d35 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ LDIRT = config.log .dep config.status config.cache confdefs.h conftest* \ Logs/* built .census install.* install-dev.* *.gz SUBDIRS = include libxfs libxlog libxcmd libhandle libdisk \ - copy db fsck growfs io logprint mkfile mkfs quota repair rtcp \ + copy db fsck growfs io logprint mkfs quota repair rtcp \ m4 man doc po debian build default: $(CONFIGURE) diff --git a/VERSION b/VERSION index 0606b59a5..0516f7bcb 100644 --- a/VERSION +++ b/VERSION @@ -3,5 +3,5 @@ # PKG_MAJOR=2 PKG_MINOR=7 -PKG_REVISION=7 +PKG_REVISION=8 PKG_BUILD=1 diff --git a/debian/changelog b/debian/changelog index bd3466031..4d91ece2e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +xfsprogs (2.7.8-1) unstable; urgency=low + + * New upstream release. + + -- Nathan Scott Mon, 05 Dec 2005 15:12:06 +1100 + xfsprogs (2.7.7-1) unstable; urgency=low * New upstream release. diff --git a/doc/CHANGES b/doc/CHANGES index 70886d7db..db7a1387d 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -1,3 +1,8 @@ +xfsprogs-2.7.8 (05 December 2005) + - Extend xfs_io to do aligned direct IO automatically + - Report direct IO parameters (dioinfo) in xfs_io + - Make xfs_mkfile a shell script wrapper around xfs_io + xfsprogs-2.7.7 (16 November 2005) - Fix some gcc compiler warnings on 64 bit platforms. - Remove last reference to a (kernel) header. diff --git a/io/Makefile b/io/Makefile index 3c857d36c..4a0ab6657 100644 --- a/io/Makefile +++ b/io/Makefile @@ -6,7 +6,7 @@ TOPDIR = .. include $(TOPDIR)/include/builddefs LTCOMMAND = xfs_io -LSRCFILES = xfs_bmap.sh xfs_freeze.sh +LSRCFILES = xfs_bmap.sh xfs_freeze.sh xfs_mkfile.sh HFILES = init.h io.h CFILES = init.c \ attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c mmap.c \ @@ -73,4 +73,5 @@ install: default $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) $(LTINSTALL) -m 755 xfs_bmap.sh $(PKG_BIN_DIR)/xfs_bmap $(LTINSTALL) -m 755 xfs_freeze.sh $(PKG_BIN_DIR)/xfs_freeze + $(LTINSTALL) -m 755 xfs_mkfile.sh $(PKG_BIN_DIR)/xfs_mkfile install-dev: diff --git a/io/io.h b/io/io.h index 9a4b03d9f..b04ab2c2a 100644 --- a/io/io.h +++ b/io/io.h @@ -82,6 +82,7 @@ extern unsigned int recurse_dir; extern void *buffer; extern size_t buffersize; +extern int align_direct(off64_t *, long long *); extern int alloc_buffer(size_t, int, unsigned int); extern int read_buffer(int, off64_t, long long, long long *, int, int); diff --git a/io/open.c b/io/open.c index 741dfafaa..bd4ff5dab 100644 --- a/io/open.c +++ b/io/open.c @@ -72,7 +72,8 @@ stat_f( int argc, char **argv) { - struct fsxattr fsx; + struct dioattr dio; + struct fsxattr fsx, fsxa; struct stat64 st; int verbose = (argc == 2 && !strcmp(argv[1], "-v")); @@ -99,13 +100,23 @@ stat_f( } if (file->flags & IO_FOREIGN) return 0; - if ((xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { + if ((xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTR, &fsx)) < 0 || + (xfsctl(file->name, file->fd, XFS_IOC_FSGETXATTRA, &fsxa)) < 0) { perror("XFS_IOC_FSGETXATTR"); } else { - printf(_("xattr.xflags = 0x%x "), fsx.fsx_xflags); + printf(_("fsxattr.xflags = 0x%x "), fsx.fsx_xflags); printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1); - printf(_("xattr.extsize = %u\n"), fsx.fsx_extsize); - printf(_("xattr.nextents = %u\n"), fsx.fsx_nextents); + printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid); + printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize); + printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents); + printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents); + } + if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) { + perror("XFS_IOC_DIOINFO"); + } else { + printf(_("dioattr.mem = 0x%x\n"), dio.d_mem); + printf(_("dioattr.miniosz = %u\n"), dio.d_miniosz); + printf(_("dioattr.maxiosz = %u\n"), dio.d_maxiosz); } return 0; } diff --git a/io/pread.c b/io/pread.c index b93e27f53..dcfec0339 100644 --- a/io/pread.c +++ b/io/pread.c @@ -105,6 +105,36 @@ dump_buffer( } } +int +align_direct( + off64_t *offset, + long long *count) +{ + struct dioattr dio; + unsigned int align; + + if (!(file->flags & IO_DIRECT)) + return 0; + + if (file->flags & IO_FOREIGN) { + dio.d_miniosz = BBSIZE; /* punt */ + } else if ((xfsctl(file->name, file->fd, XFS_IOC_DIOINFO, &dio)) < 0) { + perror("XFS_IOC_DIOINFO"); + return 1; + } + + align = (*offset % dio.d_miniosz); + if (align) { + *offset -= align; + *count += align; + } + align = (*count % dio.d_miniosz); + if (align) { + *count += (dio.d_miniosz - align); + } + return 0; +} + static int read_random( int fd, @@ -270,15 +300,15 @@ pread_f( struct timeval t1, t2; char s1[64], s2[64], ts[64]; char *sp; - int Cflag, uflag, vflag; + int Cflag, qflag, uflag, vflag; int eof = 0, direction = IO_FORWARD; int c; - Cflag = uflag = vflag = 0; + Cflag = qflag = uflag = vflag = 0; init_cvtnum(&fsblocksize, &fssectsize); bsize = fsblocksize; - while ((c = getopt(argc, argv, "b:BCFRuvZ:")) != EOF) { + while ((c = getopt(argc, argv, "b:BCFRquvZ:")) != EOF) { switch (c) { case 'b': tmp = cvtnum(fsblocksize, fssectsize, optarg); @@ -300,6 +330,9 @@ pread_f( case 'R': direction = IO_RANDOM; break; + case 'q': + qflag = 1; + break; case 'u': uflag = 1; break; @@ -335,8 +368,11 @@ pread_f( printf(_("non-numeric length argument -- %s\n"), argv[optind]); return 0; } + if (alloc_buffer(bsize, uflag, 0xabababab) < 0) return 0; + if (align_direct(&offset, &count) < 0) + return 0; gettimeofday(&t1, NULL); switch (direction) { @@ -358,6 +394,8 @@ pread_f( } if (c < 0) return 0; + if (qflag) + return 0; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); diff --git a/io/pwrite.c b/io/pwrite.c index 595ba33c3..6e3833d10 100644 --- a/io/pwrite.c +++ b/io/pwrite.c @@ -199,15 +199,15 @@ pwrite_f( struct timeval t1, t2; char s1[64], s2[64], ts[64]; char *sp, *infile = NULL; - int Cflag, uflag, dflag, wflag, Wflag; + int Cflag, qflag, uflag, dflag, wflag, Wflag; int direction = IO_FORWARD; int c, fd = -1; - Cflag = uflag = dflag = wflag = Wflag = 0; + Cflag = qflag = uflag = dflag = wflag = Wflag = 0; init_cvtnum(&fsblocksize, &fssectsize); bsize = fsblocksize; - while ((c = getopt(argc, argv, "b:Cdf:i:s:S:uwWZ:")) != EOF) { + while ((c = getopt(argc, argv, "b:Cdf:i:qs:S:uwWZ:")) != EOF) { switch (c) { case 'b': tmp = cvtnum(fsblocksize, fssectsize, optarg); @@ -250,6 +250,9 @@ pwrite_f( return 0; } break; + case 'q': + qflag = 1; + break; case 'u': uflag = 1; break; @@ -288,6 +291,8 @@ pwrite_f( if (alloc_buffer(bsize, uflag, seed) < 0) return 0; + if (align_direct(&offset, &count) < 0) + return 0; c = IO_READONLY | (dflag ? IO_DIRECT : 0); if (infile && ((fd = openfile(infile, NULL, c, 0)) < 0)) @@ -309,14 +314,14 @@ pwrite_f( default: ASSERT(0); } - if (c < 0) { - close(fd); - return 0; - } + if (c < 0) + goto done; if (Wflag) fsync(file->fd); if (wflag) fdatasync(file->fd); + if (qflag) + goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); @@ -334,6 +339,7 @@ pwrite_f( total, c, ts, tdiv((double)total, t2), tdiv((double)c, t2)); } +done: close(fd); return 0; } diff --git a/io/sendfile.c b/io/sendfile.c index a36f8bb74..4b34a5f05 100644 --- a/io/sendfile.c +++ b/io/sendfile.c @@ -84,15 +84,19 @@ sendfile_f( struct timeval t1, t2; char s1[64], s2[64], ts[64]; char *infile = NULL; - int Cflag; + int Cflag, qflag; int c, fd = -1; - Cflag = 0; + Cflag = qflag = 0; init_cvtnum(&blocksize, §size); - while ((c = getopt(argc, argv, "Cf:i:")) != EOF) { + while ((c = getopt(argc, argv, "Cf:i:q")) != EOF) { switch (c) { case 'C': Cflag = 1; + break; + case 'q': + qflag = 1; + break; case 'f': fd = atoi(argv[1]); if (fd < 0 || fd >= filecount) { @@ -144,6 +148,8 @@ sendfile_f( c = send_buffer(offset, count, fd, &total); if (c < 0) goto done; + if (qflag) + goto done; gettimeofday(&t2, NULL); t2 = tsub(t2, t1); diff --git a/io/xfs_mkfile.sh b/io/xfs_mkfile.sh new file mode 100755 index 000000000..b07edc47c --- /dev/null +++ b/io/xfs_mkfile.sh @@ -0,0 +1,53 @@ +#!/bin/sh -f +# +# Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. +# + +OPTS="" +NOBYTES=false +PREALLOC=false +VERBOSE=false +VERSION=false +XFS_IO=`dirname $0`"/xfs_io -p xfs_mkfile" +USAGE="Usage: xfs_mkfile [-npvV] size file..." + +while getopts "npvV" c +do + case $c in + n) NOBYTES=true;; + p) PREALLOC=true;; + v) VERBOSE=true;; + V) VERSION=true;; + \?) echo $USAGE 1>&2 + exit 2 + ;; + esac +done +$VERSION && $XFS_IO -V + +shift `expr $OPTIND - 1` +[ "$1" != "" ] || exit 0 +SIZE="$1" +ERRORS=0 +shift + +while [ "$1" != "" ] +do + if $VERBOSE ; then + $PREALLOC && echo "$1 $SIZE bytes pre-allocated" + $PREALLOC || echo "$1 $SIZE bytes" + fi + if $NOBYTES ; then + $XFS_IO -ft -c "truncate $SIZE" -- "$1" + elif $PREALLOC ; then + $XFS_IO -ftd -c "resvsp 0 $SIZE" \ + -c "pwrite -q -S0 -b256k 0 $SIZE" \ + -c "truncate $SIZE" -- "$1" + else + $XFS_IO -ftd -c "pwrite -q -S0 -b256k 0 $SIZE" \ + -c "truncate $SIZE" -- "$1" + fi + [ $? -eq 0 ] || ERRORS=`expr $ERRORS + 1` + shift +done +exit $ERRORS diff --git a/libxcmd/input.c b/libxcmd/input.c index 5814e2212..f5b8b3d1e 100644 --- a/libxcmd/input.c +++ b/libxcmd/input.c @@ -149,6 +149,7 @@ cvtnum( { long long i; char *sp; + int c; i = strtoll(s, &sp, 0); if (i == 0 && sp == s) @@ -156,22 +157,28 @@ cvtnum( if (*sp == '\0') return i; - if (*sp == 'b' && sp[1] == '\0') + if (sp[1] == '\0') + return -1LL; + + c = tolower(*sp); + switch (c) { + case 'b': return i * blocksize; - if (*sp == 's' && sp[1] == '\0') + case 's': return i * sectorsize; - if (*sp == 'k' && sp[1] == '\0') + case 'k': return KILOBYTES(i); - if (*sp == 'm' && sp[1] == '\0') + case 'm': return MEGABYTES(i); - if (*sp == 'g' && sp[1] == '\0') + case 'g': return GIGABYTES(i); - if (*sp == 't' && sp[1] == '\0') + case 't': return TERABYTES(i); - if (*sp == 'p' && sp[1] == '\0') + case 'p': return PETABYTES(i); - if (*sp == 'e' && sp[1] == '\0') + case 'e': return EXABYTES(i); + } return -1LL; } diff --git a/mkfile/Makefile b/mkfile/Makefile deleted file mode 100644 index e7ab49c95..000000000 --- a/mkfile/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved. -# - -TOPDIR = .. -include $(TOPDIR)/include/builddefs - -LTCOMMAND = xfs_mkfile -CFILES = xfs_mkfile.c -LLDFLAGS += -static - -default: $(LTCOMMAND) - -include $(BUILDRULES) - -install: default - $(INSTALL) -m 755 -d $(PKG_BIN_DIR) - $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_BIN_DIR) -install-dev: diff --git a/mkfile/xfs_mkfile.c b/mkfile/xfs_mkfile.c deleted file mode 100644 index 41f5ce59b..000000000 --- a/mkfile/xfs_mkfile.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Make file utility for xfs. - */ - -#include -#include - -#define MAXBUFFERSIZE (256 * 1024) - -char *progname; - -static void -usage(void) -{ - fprintf(stderr, _("%s: [-npv] [] ...\n"), - progname); - exit(2); -} - -static int -openfd(char *name, int oflags) -{ - int fd; - - fd = open(name, oflags, 0600); - if (fd < 0) { - perror(name); - return -1; - } - - if (!platform_test_xfs_fd(fd)) { - fprintf(stderr, _("%s: " - "file [\"%s\"] is not on an XFS filesystem\n"), - progname, name); - return -1; - } - return fd; -} - -int -main(int argc, char **argv) -{ - int fd; - char *fname; - loff_t result; - loff_t size = 0; - loff_t mult = 0; - int bytes = 0; - loff_t wrote = 0; - int len = 0; - int c; - int errflg = 0; - int errs = 0; - int nobytes = 0; - int prealloc = 0; - int verbose = 0; - struct dioattr da; - void *buf = NULL; - int buflen = 0, nbuflen; - int bufalign = 0, nbufalign, bufmin; - int oflags; - xfs_flock64_t flck; - - progname = basename(argv[0]); - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - while ((c = getopt(argc, argv, "npvV")) != EOF) { - switch(c) { - case 'n': - nobytes++; - break; - case 'p': - prealloc++; - break; - case 'v': - verbose++; - break; - case 'V': - printf(_("%s version %s\n"), progname, VERSION); - exit(0); - default: - errflg++; - break; - } - } - - if (argc < optind + 2 || errflg) - usage(); - - mult = 1; - - len = strlen(argv[optind]); - - if (isalpha((int)argv[optind][len-1])) { - switch ((int)argv[optind][len-1]) { - case 'k': - case 'K': - mult = 1024; - break; - case 'b': - case 'B': - mult = 512; - break; - case 'm': - case 'M': - mult = 1024; - mult *= 1024; - break; - case 'g': - case 'G': - mult = 1024; - mult *= 1024; - mult *= 1024; - break; - default: - fprintf(stderr, _("unknown size %s\n"), argv[optind]); - usage(); - } - - argv[optind][len-1] = '\0'; - } - - size = strtoll(argv[optind], NULL, 10) * mult; - - optind++; - - while (optind < argc) { - if (verbose) - fprintf(stdout, _("%s %lld bytes %s\n"), - argv[optind], (long long)size, - prealloc - ? _("(pre-allocated)") - : ""); - - oflags = O_CREAT|O_TRUNC|O_WRONLY|(nobytes ? 0 : O_DIRECT); - fname = argv[optind]; - - if ((fd = openfd(fname, oflags)) == -1) { - optind++; - errs++; - continue; - } - - if ( (oflags & O_DIRECT) - && ( (fd < 0 && errno == EINVAL) - || xfsctl(fname, fd, XFS_IOC_DIOINFO, &da) < 0)) { - - close(fd); - - oflags &= ~O_DIRECT; - - if ((fd = openfd(argv[optind], oflags)) == -1) { - optind++; - errs++; - continue; - } - } - - if (size == 0) { - close(fd); - optind++; - continue; - } - - if ((result = lseek64(fd, size - 1, SEEK_SET)) < 0LL) { - fprintf(stderr, _("lseek64 error, result = %lld\n"), - (long long)result); - if (errno) - perror(argv[optind]); - errs++; - } else if (nobytes) { - if (write(fd, "", 1) < 0) { - perror(argv[optind]); - errs++; - } - } else { - flck.l_whence = SEEK_SET; - flck.l_start = 0LL; - flck.l_len = size; - if (prealloc) - xfsctl(fname, fd, XFS_IOC_RESVSP64, &flck); - if (oflags & O_DIRECT) { - nbufalign = da.d_mem; - - if ( da.d_miniosz <= MAXBUFFERSIZE - && MAXBUFFERSIZE <= da.d_maxiosz) - nbuflen = MAXBUFFERSIZE; - else if (da.d_maxiosz < MAXBUFFERSIZE) - nbuflen = da.d_maxiosz; - else - nbuflen = da.d_miniosz; - - bufmin = da.d_miniosz; - } else { - nbuflen = MAXBUFFERSIZE; - nbufalign = sizeof(long); - bufmin = 0; - } - - if (nbuflen > buflen || nbufalign > bufalign) { - if (buf) - free(buf); - buf = memalign(nbufalign, nbuflen); - buflen = nbuflen; - bzero(buf, nbuflen); - nbufalign = bufalign; - } - - wrote = 0; - - lseek64(fd, 0LL, SEEK_SET); - - while (wrote < size) { - if (size - wrote >= buflen) - bytes = buflen; - else if (bufmin) - bytes = roundup(size - wrote, bufmin); - else - bytes = size - wrote; - - len = write(fd, buf, bytes); - - if (len < 0) { - perror(argv[optind]); - unlink(argv[optind]); - errs++; - break; - } - - wrote += len; - } - - if (wrote > size && ftruncate64(fd, size) < 0) { - perror(argv[optind]); - unlink(argv[optind]); - errs++; - } - } - - if ( close(fd) < 0 ) { - perror(argv[optind]); - unlink(argv[optind]); - errs++; - } - - optind++; - } - - return errs != 0; -} -- 2.47.2