From: Nathan Scott Date: Tue, 8 Aug 2006 15:32:10 +0000 (+0000) Subject: Allow tools to use direct IO on Linux when reading from the device, if teh device... X-Git-Tag: v2.9.0~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b74a1f6a9fae86ae782fd3968d5ab52d14d13f3a;p=thirdparty%2Fxfsprogs-dev.git Allow tools to use direct IO on Linux when reading from the device, if teh device supports it, and if the tools is OK with that (most are). Mainly for xfs_repair speedups, now that libxfs caches metadata buffers internally. Merge of master-melb:xfs-cmds:26728a by kenmcd. --- diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c index 81cd1c641..6af8c0ec0 100644 --- a/copy/xfs_copy.c +++ b/copy/xfs_copy.c @@ -652,6 +652,7 @@ main(int argc, char **argv) memset(&xargs, 0, sizeof(xargs)); xargs.notvolmsg = "oh no %s"; + xargs.isdirect = LIBXFS_DIRECT; xargs.isreadonly = LIBXFS_ISREADONLY; xargs.notvolok = 1; diff --git a/include/libxfs.h b/include/libxfs.h index 707cb3839..6ad5925eb 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -68,6 +68,7 @@ typedef struct { char *logname; /* pathname of log "subvolume" */ char *rtname; /* pathname of realtime "subvolume" */ int isreadonly; /* filesystem is only read in applic */ + int isdirect; /* we can attempt to use direct I/O */ int disfile; /* data "subvolume" is a regular file */ int dcreat; /* try to create data subvolume */ int lisfile; /* log "subvolume" is a regular file */ int lcreat; /* try to create log subvolume */ @@ -98,6 +99,7 @@ typedef struct { #define LIBXFS_ISINACTIVE 0x0004 /* allow mounted only if mounted ro */ #define LIBXFS_DANGEROUSLY 0x0008 /* repairing a device mounted ro */ #define LIBXFS_EXCLUSIVELY 0x0010 /* disallow other accesses (O_EXCL) */ +#define LIBXFS_DIRECT 0x0020 /* can use direct I/O, not buffered */ extern char *progname; extern int libxfs_init (libxfs_init_t *); @@ -106,8 +108,8 @@ extern int libxfs_device_to_fd (dev_t); extern dev_t libxfs_device_open (char *, int, int, int); extern void libxfs_device_zero (dev_t, xfs_daddr_t, uint); extern void libxfs_device_close (dev_t); +extern int libxfs_device_alignment (void); extern void libxfs_report(FILE *); -extern char *libxfs_findrawpath(char *); /* check or write log footer: specify device, log size in blocks & uuid */ typedef xfs_caddr_t (libxfs_get_block_t)(xfs_caddr_t, int, void *); diff --git a/libxfs/darwin.c b/libxfs/darwin.c index 60780b049..59e479271 100644 --- a/libxfs/darwin.c +++ b/libxfs/darwin.c @@ -92,17 +92,29 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) int platform_aio_init(int aio_count) { - return (0); /* aio/lio_listio not available */ + return 0; /* aio/lio_listio not available */ } char * platform_findrawpath(char *path) { - return (path); + return path; } -size_t -platform_memalignment(void) +char * +platform_findblockpath(char *path) +{ + return path; +} + +int +platform_direct_blockdev(void) +{ + return 0; +} + +int +platform_align_blockdev(void) { - return sizeof(void *); + return (sizeof(void *)); } diff --git a/libxfs/freebsd.c b/libxfs/freebsd.c index 26ef3a10f..a179fa8a6 100644 --- a/libxfs/freebsd.c +++ b/libxfs/freebsd.c @@ -152,17 +152,29 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) int platform_aio_init(int aio_count) { - return (0); /* aio/lio_listio not available */ + return 0; /* aio/lio_listio not available */ } char * platform_findrawpath(char *path) { - return (path); + return path; } -size_t -platform_memalignment(void) +char * +platform_findblockpath(char *path) +{ + return path; +} + +int +platform_direct_blockdev(void) +{ + return 0; +} + +int +platform_align_blockdev(void) { - return sizeof(void *); + return (sizeof(void *)); } diff --git a/libxfs/init.c b/libxfs/init.c index 212cb1eff..e5d4b9850 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -20,9 +20,6 @@ #include #include "init.h" -#define findrawpath(x) x -#define findblockpath(x) x - char *progname = "libxfs"; /* default, changed by each tool */ struct cache *libxfs_icache; /* global inode cache */ @@ -92,16 +89,22 @@ libxfs_device_open(char *path, int creat, int xflags, int setblksize) { dev_t dev; int fd, d, flags; - int readonly, excl; + int readonly, dio, excl; struct stat64 statb; readonly = (xflags & LIBXFS_ISREADONLY); excl = (xflags & LIBXFS_EXCLUSIVELY) && !creat; + dio = (xflags & LIBXFS_DIRECT) && !creat && platform_direct_blockdev(); +retry: flags = (readonly ? O_RDONLY : O_RDWR) | \ (creat ? (O_CREAT|O_TRUNC) : 0) | \ + (dio ? O_DIRECT : 0) | \ (excl ? O_EXCL : 0); + if ((fd = open(path, flags, 0666)) < 0) { + if (errno == EINVAL && --dio == 0) + goto retry; fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, path, strerror(errno)); exit(1); @@ -181,13 +184,13 @@ check_open(char *path, int flags, char **rawfile, char **blockfile) perror(path); return 0; } - if (!(*rawfile = findrawpath(path))) { + if (!(*rawfile = platform_findrawpath(path))) { fprintf(stderr, _("%s: " "can't find a character device matching %s\n"), progname, path); return 0; } - if (!(*blockfile = findblockpath(path))) { + if (!(*blockfile = platform_findblockpath(path))) { fprintf(stderr, _("%s: " "can't find a block device matching %s\n"), progname, path); @@ -235,7 +238,7 @@ libxfs_init(libxfs_init_t *a) (void)getcwd(curdir,MAXPATHLEN); needcd = 0; fd = -1; - flags = a->isreadonly; + flags = (a->isreadonly | a->isdirect); if (a->volname) { if(!check_open(a->volname,flags,&rawfile,&blockfile)) @@ -753,6 +756,12 @@ libxfs_destroy(void) cache_destroy(libxfs_bcache); } +int +libxfs_device_alignment(void) +{ + return platform_align_blockdev(); +} + void libxfs_report(FILE *fp) { @@ -766,9 +775,3 @@ libxfs_report(FILE *fp) c = asctime(localtime(&t)); fprintf(fp, "%s", c); } - -char * -libxfs_findrawpath(char *path) -{ - return platform_findrawpath(path); -} diff --git a/libxfs/init.h b/libxfs/init.h index 4fc62841c..60e89902c 100644 --- a/libxfs/init.h +++ b/libxfs/init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005 Silicon Graphics, Inc. + * Copyright (c) 2000-2006 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -28,6 +28,10 @@ extern void platform_findsizes (char *path, int fd, long long *sz, int *bsz); extern void platform_set_blocksize (int fd, char *path, int blocksize); extern void platform_flush_device (int fd, dev_t device); extern char *platform_findrawpath(char *path); -extern int platform_aio_init(int aio_count); -extern size_t platform_memalignment(void); +extern char *platform_findrawpath (char *path); +extern char *platform_findblockpath (char *path); +extern int platform_direct_blockdev (void); +extern int platform_align_blockdev (void); +extern int platform_aio_init (int aio_count); + #endif /* LIBXFS_INIT_H */ diff --git a/libxfs/irix.c b/libxfs/irix.c index d37a9783a..b0f637aac 100644 --- a/libxfs/irix.c +++ b/libxfs/irix.c @@ -85,8 +85,20 @@ platform_findrawpath(char *path) return findrawpath(path); } -size_t -platform_memalignment(void) +char * +platform_findblockpath(char *path) +{ + return findblockpath(path); +} + +int +platform_direct_blockdev(void) +{ + return 0; +} + +int +platform_align_blockdev(void) { - return sizeof(void *); + return (sizeof(void *)); } diff --git a/libxfs/linux.c b/libxfs/linux.c index 818904932..f2d975c43 100644 --- a/libxfs/linux.c +++ b/libxfs/linux.c @@ -27,6 +27,7 @@ #include extern char *progname; +static int max_block_alignment; #ifndef BLKGETSIZE64 # define BLKGETSIZE64 _IOR(0x12,114,size_t) @@ -134,6 +135,8 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) if ((st.st_mode & S_IFMT) == S_IFREG) { *sz = (long long)(st.st_size >> 9); *bsz = BBSIZE; + if (BBSIZE > max_block_alignment) + max_block_alignment = BBSIZE; return; } @@ -160,6 +163,8 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) progname, path, strerror(errno)); *bsz = BBSIZE; } + if (*bsz > max_block_alignment) + max_block_alignment = *bsz; } int @@ -178,7 +183,27 @@ platform_aio_init(int aio_count) char * platform_findrawpath(char *path) { - return (path); + return path; +} + +char * +platform_findblockpath(char *path) +{ + return path; +} + +int +platform_direct_blockdev(void) +{ + return 1; +} + +int +platform_align_blockdev(void) +{ + if (!max_block_alignment) + abort(); + return max_block_alignment; } size_t diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index d2e680f8b..76e0f109a 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -24,16 +24,6 @@ #define BDSTRAT_SIZE (256 * 1024) #define min(x, y) ((x) < (y) ? (x) : (y)) -static inline void * -libxfs_memalign(size_t size) -{ - static size_t memalignment; - - if (!memalignment) - memalignment = platform_memalignment(); - return memalign(memalignment, size); -} - void libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len) { @@ -43,7 +33,7 @@ libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len) int fd; zsize = min(BDSTRAT_SIZE, BBTOB(len)); - if ((z = libxfs_memalign(zsize)) == NULL) { + if ((z = memalign(libxfs_device_alignment(), zsize)) == NULL) { fprintf(stderr, _("%s: %s can't memalign %d bytes: %s\n"), progname, __FUNCTION__, (int)zsize, strerror(errno)); @@ -268,7 +258,8 @@ libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len) bp->b_blkno = blkno; bp->b_bcount = bytes; bp->b_dev = device; - if (!(bp->b_addr = libxfs_memalign(bytes))) { + bp->b_addr = memalign(libxfs_device_alignment(), bytes); + if (!bp->b_addr) { fprintf(stderr, _("%s: %s can't memalign %d bytes: %s\n"), progname, __FUNCTION__, (int)bytes, diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 419e6cdcc..173311069 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -636,6 +636,7 @@ main( bzero(&xi, sizeof(xi)); xi.notvolok = 1; xi.setblksize = 1; + xi.isdirect = LIBXFS_DIRECT; xi.isreadonly = LIBXFS_EXCLUSIVELY; while ((c = getopt(argc, argv, "b:d:i:l:L:n:Np:qr:s:CfV")) != EOF) { diff --git a/po/Makefile b/po/Makefile index ae932045d..b58ecbed1 100644 --- a/po/Makefile +++ b/po/Makefile @@ -85,7 +85,6 @@ XGETTEXTFILES = \ $(TOPDIR)/repair/incore_ext.c \ $(TOPDIR)/repair/incore_ino.c \ $(TOPDIR)/repair/init.c \ - $(TOPDIR)/repair/io.c \ $(TOPDIR)/repair/phase1.c \ $(TOPDIR)/repair/phase2.c \ $(TOPDIR)/repair/phase3.c \ diff --git a/repair/Makefile b/repair/Makefile index 5abe912b0..f10442a29 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -13,7 +13,7 @@ HFILES = agheader.h attr_repair.h avl.h avl64.h bmap.h dinode.h dir.h \ CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c dino_chunks.c \ dinode.c dir.c dir2.c dir_stack.c globals.c incore.c \ - incore_bmc.c init.c incore_ext.c incore_ino.c io.c phase1.c \ + incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c rt.c sb.c \ prefetch.c scan.c versions.c xfs_repair.c diff --git a/repair/globals.h b/repair/globals.h index 1e1ff5103..8194facfa 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -59,8 +59,6 @@ #define NUM_SBS 8 /* max # of sbs to verify */ #define NUM_AGH_SECTS 4 /* # of components in an ag header */ -#define MEM_ALIGN 128 /* I/O buf alignment - a cache line */ - /* * secondary sb mask -- if the secondary sb feature bits has a * the partial sb mask bit set, then you depend on the fields diff --git a/repair/init.c b/repair/init.c index 7c06f52d7..75f1f746a 100644 --- a/repair/init.c +++ b/repair/init.c @@ -130,6 +130,7 @@ xfs_init(libxfs_init_t *args) args->notvolok = 1; args->setblksize = !dangerously; + args->isdirect = LIBXFS_DIRECT; if (no_modify) args->isreadonly = (LIBXFS_ISREADONLY | LIBXFS_ISINACTIVE); else if (dangerously) diff --git a/repair/io.c b/repair/io.c deleted file mode 100644 index 8cf5e8fd9..000000000 --- a/repair/io.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2000-2002,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 - */ - -#include -#include "globals.h" -#include "agheader.h" -#include "protos.h" -#include "err_protos.h" - -void -io_init(void) -{ - /* open up filesystem device */ - - ASSERT(fs_name != NULL && *fs_name != '\0'); - - if ((fs_fd = open (fs_name, (no_modify? O_RDONLY : O_RDWR))) < 0) { - do_error(_("couldn't open filesystem \"%s\"\n"), fs_name); - } -} diff --git a/repair/phase1.c b/repair/phase1.c index e782dd837..374e3202a 100644 --- a/repair/phase1.c +++ b/repair/phase1.c @@ -35,7 +35,7 @@ alloc_ag_buf(int size) { char *bp; - bp = (char *)memalign(MEM_ALIGN, size); + bp = (char *)memalign(libxfs_device_alignment(), size); if (!bp) do_error(_("could not allocate ag header buffer (%d bytes)\n"), size); @@ -55,8 +55,6 @@ phase1(xfs_mount_t *mp) char *ag_bp; int rval; - io_init(); - do_log(_("Phase 1 - find and verify superblock...\n")); primary_sb_modified = 0; diff --git a/repair/protos.h b/repair/protos.h index 5a402789b..a70c8f159 100644 --- a/repair/protos.h +++ b/repair/protos.h @@ -17,7 +17,6 @@ */ void xfs_init(libxfs_init_t *args); -void io_init(void); int verify_sb(xfs_sb_t *sb, int is_primary_sb); diff --git a/repair/sb.c b/repair/sb.c index 3b78aa54a..702d1cdb8 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -17,6 +17,7 @@ */ #include +#include #include "agheader.h" #include "globals.h" #include "protos.h" @@ -98,7 +99,7 @@ find_secondary_sb(xfs_sb_t *rsb) do_warn(_("\nattempting to find secondary superblock...\n")); - sb = (xfs_sb_t *) memalign(MEM_ALIGN, BSIZE); + sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE); if (!sb) { do_error( _("error finding secondary superblock -- failed to memalign buffer\n")); @@ -117,11 +118,11 @@ find_secondary_sb(xfs_sb_t *rsb) /* * read disk 1 MByte at a time. */ - if (lseek64(fs_fd, off, SEEK_SET) != off) { + if (lseek64(x.dfd, off, SEEK_SET) != off) { done = 1; } - if (!done && (bsize = read(fs_fd, sb, BSIZE)) == 0) { + if (!done && (bsize = read(x.dfd, sb, BSIZE)) == 0) { done = 1; } @@ -451,19 +452,20 @@ write_primary_sb(xfs_sb_t *sbp, int size) if (no_modify) return; - if ((buf = calloc(size, 1)) == NULL) { - do_error(_("failed to malloc superblock buffer\n")); + if ((buf = memalign(libxfs_device_alignment(), size)) == NULL) { + do_error(_("failed to memalign superblock buffer\n")); return; } + memset(buf, 0, size); - if (lseek64(fs_fd, 0LL, SEEK_SET) != 0LL) { + if (lseek64(x.dfd, 0LL, SEEK_SET) != 0LL) { free(buf); do_error(_("couldn't seek to offset 0 in filesystem\n")); } libxfs_xlate_sb(buf, sbp, -1, XFS_SB_ALL_BITS); - if (write(fs_fd, buf, size) != size) { + if (write(x.dfd, buf, size) != size) { free(buf); do_error(_("primary superblock write failed!\n")); } @@ -480,27 +482,28 @@ get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno) int error, rval; void *buf; - if ((buf = calloc(size, 1)) == NULL) { + if ((buf = memalign(libxfs_device_alignment(), size)) == NULL) { do_error( - _("error reading superblock %u -- failed to malloc buffer\n"), + _("error reading superblock %u -- failed to memalign buffer\n"), agno, off); exit(1); } + memset(buf, 0, size); /* try and read it first */ - if (lseek64(fs_fd, off, SEEK_SET) != off) { + if (lseek64(x.dfd, off, SEEK_SET) != off) { do_warn( _("error reading superblock %u -- seek to offset %lld failed\n"), agno, off); return(XR_EOF); } - if ((rval = read(fs_fd, buf, size)) != size) { + if ((rval = read(x.dfd, buf, size)) != size) { error = errno; do_warn( _("superblock read failed, offset %lld, size %d, ag %u, rval %d\n"), - off, size, rval, agno); + off, size, agno, rval); do_error("%s\n", strerror(error)); } libxfs_xlate_sb(buf, sbp, 1, XFS_SB_ALL_BITS); diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 505e21e83..20cf34718 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -273,11 +273,6 @@ process_args(int argc, char **argv) if ((fs_name = argv[optind]) == NULL) usage(); - - if (!isa_file) { - if ((fs_name = libxfs_findrawpath(fs_name)) == NULL) - do_error("couldn't find raw device for %s\n", fs_name); - } } void