From: Madan Valluri Date: Fri, 30 Jun 2006 14:38:12 +0000 (+0000) Subject: Added prefetching to buffer cache via POSIX lio_listio interface. X-Git-Tag: v2.9.0~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cb5b3ef418024ed0ba6485c4eb6b5108c0480c0a;p=thirdparty%2Fxfsprogs-dev.git Added prefetching to buffer cache via POSIX lio_listio interface. Add -lrt to link line. --- diff --git a/copy/Makefile b/copy/Makefile index b93a355e8..3ba29993b 100644 --- a/copy/Makefile +++ b/copy/Makefile @@ -9,7 +9,7 @@ LTCOMMAND = xfs_copy CFILES = xfs_copy.c HFILES = xfs_copy.h -LLDLIBS = $(LIBXFS) $(LIBUUID) $(LIBPTHREAD) +LLDLIBS = $(LIBXFS) $(LIBUUID) $(LIBPTHREAD) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) LLDFLAGS = -static diff --git a/db/Makefile b/db/Makefile index 48b448402..9c8fe75d7 100644 --- a/db/Makefile +++ b/db/Makefile @@ -16,7 +16,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \ attrset.h CFILES = $(HFILES:.h=.c) LSRCFILES = xfs_admin.sh xfs_check.sh xfs_ncheck.sh -LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) +LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS += -static diff --git a/growfs/Makefile b/growfs/Makefile index c4de862f4..d853a37ee 100644 --- a/growfs/Makefile +++ b/growfs/Makefile @@ -9,7 +9,7 @@ LTCOMMAND = xfs_growfs CFILES = xfs_growfs.c -LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBUUID) +LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBUUID) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXCMD) LLDFLAGS = -static LSRCFILES = xfs_info.sh diff --git a/include/irix.h b/include/irix.h index 852b484fc..300398809 100644 --- a/include/irix.h +++ b/include/irix.h @@ -369,4 +369,6 @@ static __inline__ char * strsep(char **s, const char *ct) #define XFS_IOC_GETPARENTS SGI_XFS_GETPARENTS #define XFS_IOC_GETPARENTPATHS SGI_XFS_GETPARENTPATHS +#define _AIOCB64_T_DEFINED 1 + #endif /* __XFS_IRIX_H__ */ diff --git a/include/libxfs.h b/include/libxfs.h index 4dbe3ae49..10d7ec27b 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -107,6 +107,7 @@ 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 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 *); @@ -460,6 +461,8 @@ extern int libxfs_bmapi (xfs_trans_t *, xfs_inode_t *, xfs_fileoff_t, xfs_filblks_t, int, xfs_fsblock_t *, xfs_extlen_t, xfs_bmbt_irec_t *, int *, xfs_bmap_free_t *); +extern int libxfs_bmapi_single(xfs_trans_t *, xfs_inode_t *, int, + xfs_fsblock_t *, xfs_fileoff_t); extern int libxfs_bmap_finish (xfs_trans_t **, xfs_bmap_free_t *, xfs_fsblock_t, int *); extern int libxfs_bmap_next_offset (xfs_trans_t *, xfs_inode_t *, @@ -544,6 +547,29 @@ extern unsigned int libxfs_log2_roundup(unsigned int i); extern void cmn_err(int, char *, ...); enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC }; +/* lio interface */ +/* lio_listio(3) interface (POSIX linked asynchronous I/O) */ +extern int libxfs_lio_ino_count; +extern int libxfs_lio_dir_count; +extern int libxfs_lio_aio_count; + +extern int libxfs_lio_init(void); +extern void libxfs_lio_allocate(void); +extern void *libxfs_get_lio_buffer(int type); +extern void libxfs_put_lio_buffer(void *buffer); +extern int libxfs_readbuf_list(dev_t dev, int nent, void *voidp, int type); + +typedef struct libxfs_lio_req { + xfs_daddr_t blkno; + int len; /* bbs */ +} libxfs_lio_req_t; + +#define LIBXFS_LIO_TYPE_INO 0x1 +#define LIBXFS_LIO_TYPE_DIR 0x2 +#define LIBXFS_LIO_TYPE_RAW 0x3 + +#define LIBXFS_BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT) + #include #include diff --git a/include/linux.h b/include/linux.h index 62b8e58d9..152efc53c 100644 --- a/include/linux.h +++ b/include/linux.h @@ -119,4 +119,9 @@ typedef enum {B_FALSE, B_TRUE} boolean_t; #define _BOOLEAN_T_DEFINED 1 #endif -#endif /* __XFS_IRIX_H__ */ +#ifdef __USE_GNU +typedef struct aiocb64 aiocb64_t; +#define _AIOCB64_T_DEFINED 1 +#endif + +#endif /* __XFS_LINUX_H__ */ diff --git a/libxfs/Makefile b/libxfs/Makefile index 8cc780ec8..4ab4625b3 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -10,8 +10,8 @@ LT_CURRENT = 0 LT_REVISION = 0 LT_AGE = 0 -HFILES = xfs.h init.h -CFILES = bit.c cache.c init.c logitem.c rdwr.c trans.c util.c \ +HFILES = xfs.h init.h list.h +CFILES = bit.c cache.c init.c lio.c logitem.c rdwr.c trans.c util.c \ xfs_alloc.c xfs_ialloc.c xfs_rtalloc.c \ xfs_inode.c xfs_btree.c xfs_alloc_btree.c xfs_ialloc_btree.c \ xfs_bmap_btree.c xfs_da_btree.c xfs_dir.c xfs_dir_leaf.c \ diff --git a/libxfs/darwin.c b/libxfs/darwin.c index 076402c2f..4cdbe7e90 100644 --- a/libxfs/darwin.c +++ b/libxfs/darwin.c @@ -87,3 +87,16 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) *sz = (long long)size; *bsz = BBSIZE; } + +/* ARGSUSED */ +int +platform_aio_init(int aio_count) +{ + return (0); /* aio/lio_listio not available */ +} + +char * +platform_findrawpath(char *path) +{ + return (path); +} diff --git a/libxfs/freebsd.c b/libxfs/freebsd.c index 5bf029430..845533b0b 100644 --- a/libxfs/freebsd.c +++ b/libxfs/freebsd.c @@ -147,3 +147,16 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) *sz = (long long) (size / ssize); *bsz = (int)ssize; } + +/* ARGSUSED */ +int +platform_aio_init(int aio_count) +{ + return (0); /* aio/lio_listio not available */ +} + +char * +platform_findrawpath(char *path) +{ + return (path); +} diff --git a/libxfs/init.c b/libxfs/init.c index 1e6e9bf46..212cb1eff 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -756,6 +756,19 @@ libxfs_destroy(void) void libxfs_report(FILE *fp) { + time_t t; + char *c; + cache_report(fp, "libxfs_icache", libxfs_icache); cache_report(fp, "libxfs_bcache", libxfs_bcache); + + t = time(NULL); + 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 741624ad8..d54d8d4dc 100644 --- a/libxfs/init.h +++ b/libxfs/init.h @@ -27,5 +27,6 @@ extern int platform_check_iswritable (char *path, char *block, 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); #endif /* LIBXFS_INIT_H */ diff --git a/libxfs/irix.c b/libxfs/irix.c index 4371ab5d5..28f471d91 100644 --- a/libxfs/irix.c +++ b/libxfs/irix.c @@ -17,6 +17,8 @@ */ #include +#include +#include extern char *progname; extern __int64_t findsize(char *); @@ -63,3 +65,22 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) } *bsz = BBSIZE; } + +int +platform_aio_init(int aio_count) +{ + struct aioinit aio_init; + + memset(&aio_init, 0, sizeof(aio_init)); + aio_init.aio_threads = aio_count; + aio_init.aio_numusers = aio_count; + + aio_sgi_init64(&aio_init); + return (1); /* aio/lio_listio available */ +} + +char * +platform_findrawpath(char *path) +{ + return findrawpath(path); +} diff --git a/libxfs/linux.c b/libxfs/linux.c index 6aaea3826..2b2d59440 100644 --- a/libxfs/linux.c +++ b/libxfs/linux.c @@ -20,6 +20,7 @@ #include #include #include +#include #undef ustat #include #include @@ -160,3 +161,22 @@ platform_findsizes(char *path, int fd, long long *sz, int *bsz) *bsz = BBSIZE; } } + +int +platform_aio_init(int aio_count) +{ + struct aioinit lcl_aio_init; + + memset(&lcl_aio_init, 0, sizeof(lcl_aio_init)); + lcl_aio_init.aio_threads = aio_count; + lcl_aio_init.aio_numusers = aio_count; + + aio_init(&lcl_aio_init); + return (1); /* aio/lio_listio available */ +} + +char * +platform_findrawpath(char *path) +{ + return (path); +} diff --git a/libxfs/lio.c b/libxfs/lio.c new file mode 100644 index 000000000..c1d1712bd --- /dev/null +++ b/libxfs/lio.c @@ -0,0 +1,192 @@ +#include +#include "init.h" +#include "aio.h" + +#define DEF_PREFETCH_INOS 16 +#define DEF_PREFETCH_DIRS 16 +#define DEF_PREFETCH_AIO 32 +int libxfs_lio_ino_count = DEF_PREFETCH_INOS; +int libxfs_lio_dir_count = DEF_PREFETCH_DIRS; +int libxfs_lio_aio_count = DEF_PREFETCH_AIO; + +static pthread_key_t lio_ino_key; +static pthread_key_t lio_dir_key; + +void +libxfs_lio_allocate(void) +{ +#ifdef _AIOCB64_T_DEFINED + size_t size; + void *voidp; + + /* + * allocate a per-thread buffer which will be used in libxfs_readbuf_list + * in the following order: + * libxfs_lio_req_t array + * aiocb64_t array + * aiocb64_t * array + * xfs_buf_t * array + */ + size = sizeof(libxfs_lio_req_t) + sizeof(aiocb64_t) + sizeof(aiocb64_t *) + sizeof(xfs_buf_t *); + + voidp = malloc(libxfs_lio_ino_count*size); + if (voidp == NULL) { + fprintf(stderr, "lio_allocate: cannot allocate thread specific storage\n"); + exit(1); + /* NO RETURN */ + return; + } + pthread_setspecific(lio_ino_key, voidp); + + voidp = malloc(libxfs_lio_dir_count*size); + if (voidp == NULL) { + fprintf(stderr, "lio_allocate: cannot allocate thread specific storage\n"); + exit(1); + /* NO RETURN */ + return; + } + pthread_setspecific(lio_dir_key, voidp); +#endif /* _AIOCB64_T_DEFINED */ +} + +int +libxfs_lio_init(void) +{ +#ifdef _AIOCB64_T_DEFINED + if (platform_aio_init(libxfs_lio_aio_count)) { + pthread_key_create(&lio_ino_key, NULL); + pthread_key_create(&lio_dir_key, NULL); + return (1); + } +#endif /* _AIOCB64_T_DEFINED */ + return (0); +} + +void * +libxfs_get_lio_buffer(int type) +{ +#ifdef _AIOCB64_T_DEFINED + if (type == LIBXFS_LIO_TYPE_INO) + return pthread_getspecific(lio_ino_key); + if (type == LIBXFS_LIO_TYPE_DIR) + return pthread_getspecific(lio_dir_key); + if (type == LIBXFS_LIO_TYPE_RAW) { + /* use the inode buffers since there is + * no overlap with the other requests. + */ + return pthread_getspecific(lio_ino_key); + } + fprintf(stderr, "get_lio_buffer: invalid type 0x%x\n", type); + exit(1); +#endif + return NULL; +} + +/* ARGSUSED */ +void +libxfs_put_lio_buffer(void *buffer) +{ + return; /* nothing to do */ +} + +static int +lio_compare(const void *e1, const void *e2) +{ + libxfs_lio_req_t *r1 = (libxfs_lio_req_t *) e1; + libxfs_lio_req_t *r2 = (libxfs_lio_req_t *) e2; + + return (int) (r1->blkno - r2->blkno); +} + +int +libxfs_readbuf_list(dev_t dev, int nent, void *voidp, int type) +{ +#ifdef _AIOCB64_T_DEFINED + libxfs_lio_req_t *rblp; + xfs_buf_t *bp, **bplist; + aiocb64_t *aioclist, **aiocptr; + int i, nbp, err; + int fd; + + if (nent <= 0) + return 0; + if ((type == LIBXFS_LIO_TYPE_INO) || (type == LIBXFS_LIO_TYPE_RAW)) { + if (libxfs_lio_ino_count == 0) + return (0); + if (nent > libxfs_lio_ino_count) + nent = libxfs_lio_ino_count; + } + else if (type == LIBXFS_LIO_TYPE_DIR) { + if (libxfs_lio_dir_count == 0) + return (0); + if (nent > libxfs_lio_dir_count) + nent = libxfs_lio_dir_count; + if (nent > 2) + qsort(voidp, nent, sizeof(libxfs_lio_req_t), lio_compare); + } + else { + fprintf(stderr, "Invalid type 0x%x in libxfs_readbuf_list\n", type); + abort(); + /* NO RETURN */ + return (0); + } + + /* space for lio_listio processing, see libxfs_lio_allocate */ + rblp = (libxfs_lio_req_t *) voidp; + aioclist = (aiocb64_t *) (rblp + nent); + aiocptr = (aiocb64_t **) (aioclist + nent); + bplist = (xfs_buf_t **) (aiocptr + nent); + + bzero(aioclist, nent*sizeof(aiocb64_t)); + + /* look in buffer cache */ + for (i = 0, nbp = 0; i < nent; i++) { + ASSERT(rblp[i].len); + bp = libxfs_getbuf(dev, rblp[i].blkno, rblp[i].len); + if (bp == NULL) + continue; + if (bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY)) { + /* already in cache */ + libxfs_putbuf(bp); + continue; + } + bplist[nbp++] = bp; + } + + if (nbp == 0) + return (0); /* Nothing to do */ + + if (nbp == 1) { + libxfs_putbuf(bplist[0]); /* single buffer, no point */ + return (0); + } + + fd = libxfs_device_to_fd(dev); + + for (i = 0; i < nbp; i++) { + aioclist[i].aio_fildes = fd; + aioclist[i].aio_nbytes = XFS_BUF_COUNT(bplist[i]); + aioclist[i].aio_buf = XFS_BUF_PTR(bplist[i]); + aioclist[i].aio_offset = LIBXFS_BBTOOFF64(XFS_BUF_ADDR(bplist[i])); + aioclist[i].aio_lio_opcode = LIO_READ; + aiocptr[i] = &aioclist[i]; + } + + err = lio_listio64(LIO_WAIT, aiocptr, nbp, NULL); + + if (err != 0) { + fprintf(stderr, "lio_listio (%d entries) failure err = %d\n", nbp, err); + } + + for (i = 0; i < nbp; i++) { + /* buffer with data in cache available via future libxfs_readbuf */ + if (err == 0) + bplist[i]->b_flags |= LIBXFS_B_UPTODATE; + libxfs_putbuf(bplist[i]); + } + + return (err == 0? nbp : -1); +#else /* _AIOCB64_T_DEFINED */ + return -1; +#endif /* _AIOCB64_T_DEFINED */ +} diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index 0d0f9d83c..24648c176 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -20,7 +20,6 @@ #include #include -#define BBTOOFF64(bbs) (((xfs_off_t)(bbs)) << BBSHIFT) #define BDSTRAT_SIZE (256 * 1024) #define min(x, y) ((x) < (y) ? (x) : (y)) @@ -52,7 +51,7 @@ libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len) memset(z, 0, zsize); fd = libxfs_device_to_fd(dev); - start_offset = BBTOOFF64(start); + start_offset = LIBXFS_BBTOOFF64(start); if ((lseek64(fd, start_offset, SEEK_SET)) < 0) { fprintf(stderr, _("%s: %s seek to offset %llu failed: %s\n"), @@ -61,7 +60,7 @@ libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len) exit(1); } - end_offset = BBTOOFF64(start + len) - start_offset; + end_offset = LIBXFS_BBTOOFF64(start + len) - start_offset; for (offset = 0; offset < end_offset; ) { bytes = min((ssize_t)(end_offset - offset), zsize); if ((bytes = write(fd, z, bytes)) < 0) { @@ -262,7 +261,7 @@ libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len) if (cache_node_get(libxfs_bcache, &key, (struct cache_node **)&bp)) { #ifdef IO_DEBUG fprintf(stderr, "%s: allocated buffer, key=%llu(%llu), %p\n", - __FUNCTION__, BBTOB(len), BBTOOFF64(blkno), blkno, buf); + __FUNCTION__, BBTOB(len), LIBXFS_BBTOOFF64(blkno), blkno, buf); #endif bp->b_flags = 0; bp->b_blkno = blkno; @@ -311,7 +310,7 @@ libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags) ASSERT(BBTOB(len) <= bp->b_bcount); - if (pread64(fd, bp->b_addr, bytes, BBTOOFF64(blkno)) < 0) { + if (pread64(fd, bp->b_addr, bytes, LIBXFS_BBTOOFF64(blkno)) < 0) { fprintf(stderr, _("%s: read failed: %s\n"), progname, strerror(errno)); if (flags & LIBXFS_EXIT_ON_FAILURE) @@ -320,7 +319,7 @@ libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags) } #ifdef IO_DEBUG fprintf(stderr, "readbufr read %ubytes, blkno=%llu(%llu), %p\n", - bytes, BBTOOFF64(blkno), blkno, bp); + bytes, LIBXFS_BBTOOFF64(blkno), blkno, bp); #endif if (bp->b_dev == dev && bp->b_blkno == blkno && @@ -352,7 +351,7 @@ libxfs_writebufr(xfs_buf_t *bp) int sts; int fd = libxfs_device_to_fd(bp->b_dev); - sts = pwrite64(fd, bp->b_addr, bp->b_bcount, BBTOOFF64(bp->b_blkno)); + sts = pwrite64(fd, bp->b_addr, bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_blkno)); if (sts < 0) { fprintf(stderr, _("%s: pwrite64 failed: %s\n"), progname, strerror(errno)); @@ -369,7 +368,7 @@ libxfs_writebufr(xfs_buf_t *bp) } #ifdef IO_DEBUG fprintf(stderr, "writebufr wrote %ubytes, blkno=%llu(%llu), %p\n", - bp->b_bcount, BBTOOFF64(bp->b_blkno), bp->b_blkno, bp); + bp->b_bcount, LIBXFS_BBTOOFF64(bp->b_blkno), bp->b_blkno, bp); #endif bp->b_flags |= LIBXFS_B_UPTODATE; bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT); diff --git a/libxfs/xfs.h b/libxfs/xfs.h index d9b7106eb..060ee1881 100644 --- a/libxfs/xfs.h +++ b/libxfs/xfs.h @@ -95,6 +95,7 @@ #define xfs_iformat libxfs_iformat #define xfs_ichgtime libxfs_ichgtime #define xfs_bmapi libxfs_bmapi +#define xfs_bmapi_single libxfs_bmapi_single #define xfs_bmap_finish libxfs_bmap_finish #define xfs_bmap_del_free libxfs_bmap_del_free #define xfs_bunmapi libxfs_bunmapi diff --git a/logprint/Makefile b/logprint/Makefile index 16d69ee5e..97ded1967 100644 --- a/logprint/Makefile +++ b/logprint/Makefile @@ -12,7 +12,7 @@ CFILES = logprint.c \ log_copy.c log_dump.c log_misc.c \ log_print_all.c log_print_trans.c -LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) +LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS = -static diff --git a/mkfs/Makefile b/mkfs/Makefile index aee120466..58894a759 100644 --- a/mkfs/Makefile +++ b/mkfs/Makefile @@ -11,7 +11,7 @@ FSTYP = fstyp HFILES = xfs_mkfs.h CFILES = maxtrres.c proto.c xfs_mkfs.c -LLDLIBS = $(LIBXFS) $(LIBUUID) $(LIBDISK) +LLDLIBS = $(LIBXFS) $(LIBUUID) $(LIBDISK) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBDISK) LLDFLAGS = -static diff --git a/repair/Makefile b/repair/Makefile index 8938c31eb..5abe912b0 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -9,15 +9,15 @@ LTCOMMAND = xfs_repair HFILES = agheader.h attr_repair.h avl.h avl64.h bmap.h dinode.h dir.h \ dir2.h dir_stack.h err_protos.h globals.h incore.h protos.h rt.h \ - scan.h versions.h + scan.h versions.h prefetch.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 \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c rt.c sb.c \ - scan.c versions.c xfs_repair.c + prefetch.c scan.c versions.c xfs_repair.c -LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) +LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBPTHREAD) $(LIBRT) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) LLDFLAGS = -static diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index 2edb2bc68..e8ad51c0d 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -25,6 +25,7 @@ #include "err_protos.h" #include "dir.h" #include "dinode.h" +#include "prefetch.h" #include "versions.h" /* @@ -918,6 +919,9 @@ process_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno, { int num_inos, bogus; ino_tree_node_t *ino_rec, *first_ino_rec, *prev_ino_rec; + ino_tree_node_t *ino_ra; + + ino_ra = do_prefetch ? prefetch_inode_chunks(mp, agno, NULL) : NULL; first_ino_rec = ino_rec = findfirst_inode_rec(agno); while (ino_rec != NULL) { @@ -942,6 +946,9 @@ process_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno, ASSERT(num_inos == XFS_IALLOC_INODES(mp)); + if (do_prefetch && ino_ra && (first_ino_rec->ino_startnum >= ino_ra->ino_startnum)) + ino_ra = prefetch_inode_chunks(mp, agno, ino_ra); + if (process_inode_chunk(mp, agno, num_inos, first_ino_rec, ino_discovery, check_dups, extra_attr_check, &bogus)) { /* XXX - i/o error, we've got a problem */ diff --git a/repair/dir.c b/repair/dir.c index 254cb49bb..2117bb4e2 100644 --- a/repair/dir.c +++ b/repair/dir.c @@ -26,6 +26,7 @@ #include "dinode.h" #include "dir.h" #include "bmap.h" +#include "prefetch.h" #if XFS_DIR_LEAF_MAPSIZE >= XFS_ATTR_LEAF_MAPSIZE #define XR_DA_LEAF_MAPSIZE XFS_DIR_LEAF_MAPSIZE @@ -780,6 +781,9 @@ traverse_int_dablock(xfs_mount_t *mp, node = NULL; da_cursor->active = 0; + if (do_prefetch && (whichfork == XFS_DATA_FORK)) + prefetch_dir1(mp, bno, da_cursor); + do { /* * read in each block along the way and set up cursor diff --git a/repair/dir2.c b/repair/dir2.c index 0dc82ae44..a6438a060 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -25,6 +25,7 @@ #include "dir.h" #include "dir2.h" #include "bmap.h" +#include "prefetch.h" /* * Tag bad directory entries with this. @@ -1996,6 +1997,9 @@ process_leaf_node_dir2( int t; bmap_ext_t lbmp; + if (do_prefetch) + prefetch_dir2(mp, blkmap); + *repair = *dot = *dotdot = good = 0; *parent = NULLFSINO; ndbno = NULLDFILOFF; diff --git a/repair/init.c b/repair/init.c index e8dce55d6..7c06f52d7 100644 --- a/repair/init.c +++ b/repair/init.c @@ -22,6 +22,7 @@ #include "protos.h" #include "err_protos.h" #include "pthread.h" +#include "prefetch.h" #include static pthread_key_t dirbuf_key; @@ -139,4 +140,9 @@ xfs_init(libxfs_init_t *args) ts_init(); increase_rlimit(); + if (do_prefetch) { + do_prefetch = libxfs_lio_init(); + if (do_prefetch) + libxfs_lio_allocate(); + } } diff --git a/repair/phase6.c b/repair/phase6.c index c57a350b3..bf11490ba 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -27,6 +27,7 @@ #include "protos.h" #include "err_protos.h" #include "dinode.h" +#include "prefetch.h" #include "versions.h" static struct cred zerocr; @@ -968,6 +969,7 @@ map_first_dblock_fsbno(xfs_mount_t *mp, int i; int error; char *ftype; + xfs_fsblock_t fblock2; /* * traverse down left-side of tree until we hit the @@ -1015,6 +1017,11 @@ _("can't map block %d in %s inode %llu, xfs_bmapi returns %d, nmap = %d\n"), if (XFS_SB_VERSION_HASDIRV2(&mp->m_sb)) return(fsbno); + if (do_prefetch) { + fblock2 = NULLFSBLOCK; + prefetch_p6_dir1(mp, ino, ip, 0, &fblock2); + } + do { /* * walk down left side of btree, release buffers as you @@ -2696,6 +2703,9 @@ longform_dir2_entry_check(xfs_mount_t *mp, libxfs_dir2_isblock(NULL, ip, &isblock); libxfs_dir2_isleaf(NULL, ip, &isleaf); + if (do_prefetch && !isblock) + prefetch_p6_dir2(mp, ip); + /* check directory data */ hashtab = dir_hash_init(ip->i_d.di_size); for (da_bno = 0, next_da_bno = 0; diff --git a/repair/prefetch.c b/repair/prefetch.c new file mode 100644 index 000000000..cd198a595 --- /dev/null +++ b/repair/prefetch.c @@ -0,0 +1,466 @@ +#include +#include "prefetch.h" +#include "aio.h" +#include "avl.h" +#include "globals.h" +#include "agheader.h" +#include "incore.h" +#include "dir.h" +#include "dir2.h" +#include "dir_stack.h" +#include "protos.h" +#include "err_protos.h" +#include "dinode.h" +#include "bmap.h" +#include "versions.h" + +int do_prefetch = 1; + +ino_tree_node_t * +prefetch_inode_chunks(xfs_mount_t *mp, + xfs_agnumber_t agno, + ino_tree_node_t *ino_ra) +{ + xfs_agblock_t agbno; + libxfs_lio_req_t *liop; + int i; + + if (libxfs_lio_ino_count == 0) + return NULL; + + liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_INO); + if (liop == NULL) { + do_prefetch = 0; + return NULL; + } + + if (ino_ra == NULL) + ino_ra = findfirst_inode_rec(agno); + + i = 0; + while (ino_ra) { + agbno = XFS_AGINO_TO_AGBNO(mp, ino_ra->ino_startnum); + liop[i].blkno = XFS_AGB_TO_DADDR(mp, agno, agbno); + liop[i].len = (int) XFS_FSB_TO_BB(mp, XFS_IALLOC_BLOCKS(mp)); + i++; + ino_ra = next_ino_rec(ino_ra); + if (i >= libxfs_lio_ino_count) + break; + } + if (i) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_INO) == -1) + do_prefetch = 0; + } + libxfs_put_lio_buffer((void *) liop); + return (ino_ra); +} + +static void +prefetch_node( + xfs_mount_t *mp, + xfs_buf_t *bp, + da_bt_cursor_t *da_cursor) +{ + xfs_da_intnode_t *node; + libxfs_lio_req_t *liop; + int i; + xfs_dfsbno_t fsbno; + + node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp); + if (INT_GET(node->hdr.count, ARCH_CONVERT) <= 1) + return; + + if ((liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_DIR)) == NULL) { + return; + } + + for (i = 0; i < INT_GET(node->hdr.count, ARCH_CONVERT); i++) { + if (i == libxfs_lio_dir_count) + break; + + fsbno = blkmap_get(da_cursor->blkmap, INT_GET(node->btree[i].before, ARCH_CONVERT)); + if (fsbno == NULLDFSBNO) { + libxfs_put_lio_buffer((void *) liop); + return; + } + + liop[i].blkno = XFS_FSB_TO_DADDR(mp, fsbno); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + } + + if (i > 1) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_DIR) == -1) + do_prefetch = 0; + } + + libxfs_put_lio_buffer((void *) liop); + return; +} + +void +prefetch_dir1( + xfs_mount_t *mp, + xfs_dablk_t bno, + da_bt_cursor_t *da_cursor) +{ + xfs_da_intnode_t *node; + xfs_buf_t *bp; + xfs_dfsbno_t fsbno; + int i; + + fsbno = blkmap_get(da_cursor->blkmap, bno); + if (fsbno == NULLDFSBNO) + return; + + bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno), + XFS_FSB_TO_BB(mp, 1), 0); + + if (bp == NULL) + return; + + + node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp); + if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) { + libxfs_putbuf(bp); + return; + } + + prefetch_node(mp, bp, da_cursor); + + /* skip prefetching if next level is leaf level */ + if (INT_GET(node->hdr.level, ARCH_CONVERT) > 1) { + for (i = 0; i < INT_GET(node->hdr.count, ARCH_CONVERT); i++) { + prefetch_dir1(mp, + INT_GET(node->btree[i].before, ARCH_CONVERT), + da_cursor); + } + } + + libxfs_putbuf(bp); + return; +} + +void +prefetch_dir2( + xfs_mount_t *mp, + blkmap_t *blkmap) +{ + xfs_dfiloff_t dbno; + xfs_dfiloff_t pdbno; + bmap_ext_t *bmp; + int nex; + int i, j, t; + libxfs_lio_req_t *liop; + + liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_DIR); + if (liop == NULL) + return; + + pdbno = NULLDFILOFF; /* previous dbno is NULLDFILOFF */ + i = 0; + while ((dbno = blkmap_next_off(blkmap, pdbno, &t)) < mp->m_dirfreeblk) { + if (i == libxfs_lio_dir_count) + break; + if (dbno == NULLDFILOFF) + break; + if (mp->m_dirblkfsbs == 1) { + xfs_dfsbno_t blk; + + /* avoid bmp realloc/free overhead, use blkmap_get */ + blk = blkmap_get(blkmap, dbno); + if (blk == NULLDFSBNO) + break; + pdbno = dbno; + liop[i].blkno = XFS_FSB_TO_DADDR(mp, blk); + liop[i].len = (int) XFS_FSB_TO_BB(mp, 1); + i++; + } + else if (mp->m_dirblkfsbs > 1) { + nex = blkmap_getn(blkmap, dbno, mp->m_dirblkfsbs, &bmp, NULL); + if (nex == 0) + break; + pdbno = dbno + mp->m_dirblkfsbs - 1; + for (j = 0; j < nex; j++) { + liop[i].blkno = XFS_FSB_TO_DADDR(mp, bmp[j].startblock); + liop[i].len = (int) XFS_FSB_TO_BB(mp, bmp[j].blockcount); + i++; + if (i == libxfs_lio_dir_count) + break; /* for loop */ + } + free(bmp); + } + else { + do_error("invalid mp->m_dirblkfsbs %d\n", mp->m_dirblkfsbs); + } + } + if (i > 1) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_DIR) == -1) + do_prefetch = 0; + } + libxfs_put_lio_buffer((void *) liop); +} + +static void +prefetch_p6_node( + xfs_mount_t *mp, + xfs_inode_t *ip, + xfs_buf_t *bp) +{ + xfs_da_intnode_t *node; + libxfs_lio_req_t *liop; + int i; + xfs_fsblock_t fblock; + xfs_dfsbno_t fsbno; + xfs_bmbt_irec_t map; + int nmap; + int error; + + node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp); + if (INT_GET(node->hdr.count, ARCH_CONVERT) <= 1) + return; + + if ((liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_DIR)) == NULL) { + return; + } + + fblock = NULLFSBLOCK; + + for (i = 0; i < INT_GET(node->hdr.count, ARCH_CONVERT); i++) { + if (i == libxfs_lio_dir_count) + break; + + nmap = 1; + error = libxfs_bmapi(NULL, ip, (xfs_fileoff_t) + INT_GET(node->btree[i].before, ARCH_CONVERT), 1, + XFS_BMAPI_METADATA, &fblock, 0, + &map, &nmap, NULL); + + if (error || (nmap != 1)) { + libxfs_put_lio_buffer((void *) liop); + return; + } + + if ((fsbno = map.br_startblock) == HOLESTARTBLOCK) { + libxfs_put_lio_buffer((void *) liop); + return; + } + liop[i].blkno = XFS_FSB_TO_DADDR(mp, fsbno); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + } + + if (i > 1) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_DIR) == -1) + do_prefetch = 0; + } + + libxfs_put_lio_buffer((void *) liop); + return; +} + +void +prefetch_p6_dir1( + xfs_mount_t *mp, + xfs_ino_t ino, + xfs_inode_t *ip, + xfs_dablk_t da_bno, + xfs_fsblock_t *fblockp) +{ + xfs_da_intnode_t *node; + xfs_buf_t *bp; + xfs_dfsbno_t fsbno; + xfs_bmbt_irec_t map; + int nmap; + int i; + int error; + + nmap = 1; + error = libxfs_bmapi(NULL, ip, (xfs_fileoff_t) da_bno, 1, + XFS_BMAPI_METADATA, fblockp, 0, + &map, &nmap, NULL); + if (error || (nmap != 1)) { + return; + } + + if ((fsbno = map.br_startblock) == HOLESTARTBLOCK) + return; + + bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, fsbno), + XFS_FSB_TO_BB(mp, 1), 0); + + if (bp == NULL) + return; + + + node = (xfs_da_intnode_t *)XFS_BUF_PTR(bp); + if (INT_GET(node->hdr.info.magic, ARCH_CONVERT) != XFS_DA_NODE_MAGIC) { + libxfs_putbuf(bp); + return; + } + + prefetch_p6_node(mp, ip, bp); + + /* skip prefetching if next level is leaf level */ + if (INT_GET(node->hdr.level, ARCH_CONVERT) > 1) { + for (i = 0; i < INT_GET(node->hdr.count, ARCH_CONVERT); i++) { + (void) prefetch_p6_dir1(mp, ino, ip, + INT_GET(node->btree[i].before, ARCH_CONVERT), + fblockp); + } + } + + libxfs_putbuf(bp); + return; +} + +#define NMAPP 4 + +void +prefetch_p6_dir2( + xfs_mount_t *mp, + xfs_inode_t *ip) +{ + xfs_fileoff_t da_bno; + xfs_fileoff_t next_da_bno; + int i, j; + libxfs_lio_req_t *liop; + xfs_fsblock_t fsb; + int nfsb; + int error; + + if ((liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_DIR)) == NULL) { + return; + } + i = 0; + for (da_bno = 0, next_da_bno = 0; next_da_bno != NULLFILEOFF; da_bno = next_da_bno) { + if (i == libxfs_lio_dir_count) + break; + next_da_bno = da_bno + mp->m_dirblkfsbs - 1; + if (libxfs_bmap_next_offset(NULL, ip, &next_da_bno, XFS_DATA_FORK)) + break; + + if (mp->m_dirblkfsbs == 1) { + if ((error = libxfs_bmapi_single(NULL, ip, XFS_DATA_FORK, &fsb, da_bno)) != 0) { + libxfs_put_lio_buffer((void *) liop); + do_prefetch = 0; + do_warn("phase6 prefetch: cannot bmap single block err = %d\n", error); + return; + } + if (fsb == NULLFSBLOCK) { + libxfs_put_lio_buffer((void *) liop); + return; + } + + liop[i].blkno = XFS_FSB_TO_DADDR(mp, fsb); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + i++; + } + else if ((nfsb = mp->m_dirblkfsbs) > 1) { + xfs_fsblock_t firstblock; + xfs_bmbt_irec_t map[NMAPP]; + xfs_bmbt_irec_t *mapp; + int nmap; + + if (nfsb > NMAPP) { + mapp = malloc(sizeof(*mapp) * nfsb); + if (mapp == NULL) { + libxfs_put_lio_buffer((void *) liop); + do_prefetch = 0; + do_warn("phase6 prefetch: cannot allocate mem for map\n"); + return; + } + } + else { + mapp = map; + } + firstblock = NULLFSBLOCK; + nmap = nfsb; + if ((error = libxfs_bmapi(NULL, ip, da_bno, + nfsb, + XFS_BMAPI_METADATA | XFS_BMAPI_AFLAG(XFS_DATA_FORK), + &firstblock, 0, mapp, &nmap, NULL))) { + libxfs_put_lio_buffer((void *) liop); + do_prefetch = 0; + do_warn("phase6 prefetch: cannot bmap err = %d\n", error); + return; + } + for (j = 0; j < nmap; j++) { + liop[i].blkno = XFS_FSB_TO_DADDR(mp, mapp[j].br_startblock); + liop[i].len = (int)XFS_FSB_TO_BB(mp, mapp[j].br_blockcount); + i++; + if (i == libxfs_lio_dir_count) + break; /* for loop */ + } + if (mapp != map) + free(mapp); + + } + else { + do_error("phase6: invalid mp->m_dirblkfsbs %d\n", mp->m_dirblkfsbs); + } + } + if (i > 1) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_DIR) == -1) + do_prefetch = 0; + } + libxfs_put_lio_buffer((void *) liop); +} + +void +prefetch_sb(xfs_mount_t *mp, xfs_agnumber_t agno) +{ + libxfs_lio_req_t *liop; + + if ((liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_RAW)) == NULL) { + do_prefetch = 0; + return; + } + + liop[0].blkno = XFS_AG_DADDR(mp, agno, XFS_SB_DADDR); + liop[1].blkno = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)); + liop[2].blkno = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)); + liop[0].len = XFS_FSS_TO_BB(mp, 1); + liop[1].len = XFS_FSS_TO_BB(mp, 1); + liop[2].len = XFS_FSS_TO_BB(mp, 1); + if (libxfs_readbuf_list(mp->m_dev, 3, (void *) liop, LIBXFS_LIO_TYPE_RAW) == -1) + do_prefetch = 0; + + libxfs_put_lio_buffer((void *) liop); +} + +void +prefetch_roots(xfs_mount_t *mp, xfs_agnumber_t agno, + xfs_agf_t *agf, xfs_agi_t *agi) +{ + int i; + libxfs_lio_req_t *liop; + + if ((liop = (libxfs_lio_req_t *) libxfs_get_lio_buffer(LIBXFS_LIO_TYPE_RAW)) == NULL) { + do_prefetch = 0; + return; + } + + i = 0; + if (agf->agf_roots[XFS_BTNUM_BNO] != 0 && + verify_agbno(mp, agno, agf->agf_roots[XFS_BTNUM_BNO])) { + liop[i].blkno = XFS_AGB_TO_DADDR(mp, agno, agf->agf_roots[XFS_BTNUM_BNO]); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + i++; + } + if (agf->agf_roots[XFS_BTNUM_CNT] != 0 && + verify_agbno(mp, agno, agf->agf_roots[XFS_BTNUM_CNT])) { + liop[i].blkno = XFS_AGB_TO_DADDR(mp, agno, agf->agf_roots[XFS_BTNUM_CNT]); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + i++; + } + if (agi->agi_root != 0 && verify_agbno(mp, agno, agi->agi_root)) { + liop[i].blkno = XFS_AGB_TO_DADDR(mp, agno, agi->agi_root); + liop[i].len = XFS_FSB_TO_BB(mp, 1); + i++; + } + if (i > 1) { + if (libxfs_readbuf_list(mp->m_dev, i, (void *) liop, LIBXFS_LIO_TYPE_RAW) == -1) + do_prefetch = 0; + } + + libxfs_put_lio_buffer((void *) liop); +} diff --git a/repair/prefetch.h b/repair/prefetch.h new file mode 100644 index 000000000..10e83ed75 --- /dev/null +++ b/repair/prefetch.h @@ -0,0 +1,45 @@ +#ifndef _XFS_REPAIR_PREFETCH_H +#define _XFS_REPAIR_PREFETCH_H + +struct blkmap; +struct da_bt_cursor; +struct xfs_mount; + +extern int do_prefetch; + +struct ino_tree_node *prefetch_inode_chunks( + struct xfs_mount *, + xfs_agnumber_t, + struct ino_tree_node *); + +extern void prefetch_dir1( + struct xfs_mount *mp, + xfs_dablk_t bno, + struct da_bt_cursor *da_cursor); + +extern void prefetch_dir2( + struct xfs_mount *mp, + struct blkmap *blkmap); + +extern void prefetch_p6_dir1( + struct xfs_mount *mp, + xfs_ino_t ino, + struct xfs_inode *ip, + xfs_dablk_t da_bno, + xfs_fsblock_t *fblockp); + +extern void prefetch_p6_dir2( + struct xfs_mount *mp, + struct xfs_inode *ip); + +extern void prefetch_sb( + struct xfs_mount *mp, + xfs_agnumber_t agno); + +extern void prefetch_roots( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agf_t *agf, + xfs_agi_t *agi); + +#endif /* _XFS_REPAIR_PREFETCH_H */ diff --git a/repair/scan.c b/repair/scan.c index 2d60cbe28..a85e5180d 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -27,6 +27,7 @@ #include "scan.h" #include "versions.h" #include "bmap.h" +#include "prefetch.h" extern int verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb, xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i); @@ -1145,6 +1146,9 @@ scan_ag( agi_dirty = agf_dirty = sb_dirty = 0; + if (do_prefetch) + prefetch_sb(mp, agno); + sbbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_SB_DADDR), XFS_FSS_TO_BB(mp, 1), 0); if (!sbbuf) { @@ -1236,6 +1240,9 @@ scan_ag( scan_freelist(agf); + if (do_prefetch) + prefetch_roots(mp, agno, agf, agi); + if (INT_GET(agf->agf_roots[XFS_BTNUM_BNO], ARCH_CONVERT) != 0 && verify_agbno(mp, agno, INT_GET(agf->agf_roots[XFS_BTNUM_BNO], ARCH_CONVERT))) diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 92c90ca7f..505e21e83 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -25,6 +25,7 @@ #include "protos.h" #include "incore.h" #include "err_protos.h" +#include "prefetch.h" #define rounddown(x, y) (((x)/(y))*(y)) @@ -56,6 +57,12 @@ char *o_opts[] = { "ihash", #define BHASH_SIZE 3 "bhash", +#define PREFETCH_INO_CNT 4 + "pfino", +#define PREFETCH_DIR_CNT 5 + "pfdir", +#define PREFETCH_AIO_CNT 6 + "pfaio", NULL }; @@ -180,7 +187,7 @@ process_args(int argc, char **argv) * XXX have to add suboption processing here * attributes, quotas, nlinks, aligned_inos, sb_fbits */ - while ((c = getopt(argc, argv, "o:fl:r:LnDvVd")) != EOF) { + while ((c = getopt(argc, argv, "o:fl:r:LnDvVdP")) != EOF) { switch (c) { case 'D': dumpcore = 1; @@ -212,6 +219,15 @@ process_args(int argc, char **argv) case BHASH_SIZE: libxfs_bhash_size = (int) strtol(val, 0, 0); break; + case PREFETCH_INO_CNT: + libxfs_lio_ino_count = (int) strtol(val, 0, 0); + break; + case PREFETCH_DIR_CNT: + libxfs_lio_dir_count = (int) strtol(val, 0, 0); + break; + case PREFETCH_AIO_CNT: + libxfs_lio_aio_count = (int) strtol(val, 0, 0); + break; default: unknown('o', val); break; @@ -244,6 +260,9 @@ process_args(int argc, char **argv) case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); + case 'P': + do_prefetch ^= 1; + break; case '?': usage(); } @@ -254,6 +273,11 @@ 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