]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Added prefetching to buffer cache via POSIX lio_listio interface.
authorMadan Valluri <mvalluri@sgi.com>
Fri, 30 Jun 2006 14:38:12 +0000 (14:38 +0000)
committerMadan Valluri <mvalluri@sgi.com>
Fri, 30 Jun 2006 14:38:12 +0000 (14:38 +0000)
Add -lrt to link line.

28 files changed:
copy/Makefile
db/Makefile
growfs/Makefile
include/irix.h
include/libxfs.h
include/linux.h
libxfs/Makefile
libxfs/darwin.c
libxfs/freebsd.c
libxfs/init.c
libxfs/init.h
libxfs/irix.c
libxfs/linux.c
libxfs/lio.c [new file with mode: 0644]
libxfs/rdwr.c
libxfs/xfs.h
logprint/Makefile
mkfs/Makefile
repair/Makefile
repair/dino_chunks.c
repair/dir.c
repair/dir2.c
repair/init.c
repair/phase6.c
repair/prefetch.c [new file with mode: 0644]
repair/prefetch.h [new file with mode: 0644]
repair/scan.c
repair/xfs_repair.c

index b93a355e8c1176498e1b6f0c45b5eedad8d9b9ea..3ba29993be23693b5ef6167f3d9be5af463d8c24 100644 (file)
@@ -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
 
index 48b4484021b3263254a5613a8e86e16a0c8ef0a0..9c8fe75d711b47b48a7323af002b9dc23d4f679c 100644 (file)
@@ -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
 
index c4de862f4334d8a8b26b8e61adbf17623fe22f94..d853a37eefd11bebe17efdc6037720e3384b5ffa 100644 (file)
@@ -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
index 852b484fcca82204a3d1310740837dcb2bda7073..3003988099fbc8a6f0224e24d38ecd2510d16575 100644 (file)
@@ -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__ */
index 4dbe3ae493d4ec6a06276c7b7f7eb54f98ae2c8c..10d7ec27b9a4620b778dbf9928bd2fb279109787 100644 (file)
@@ -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 <xfs/xfs_ialloc.h>
 #include <xfs/xfs_rtalloc.h>
 
index 62b8e58d91c0a0d8f781ecdcf1c81165d88e9180..152efc53c5c12e4ae5517273bf48412b494dee10 100644 (file)
@@ -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__ */
index 8cc780ec8331dcc5815954857d6f174f1780d92d..4ab4625b335acfe0fe3834053ff1badd1b027b92 100644 (file)
@@ -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 \
index 076402c2f3598ecfd9b92c1564ac3777f3e9cb73..4cdbe7e900f6d35ea088bb3d87d08ed6694d8607 100644 (file)
@@ -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);
+}
index 5bf029430bcdd7747053dd7c3322eb1186c35646..845533b0bfcfc34eb441392415467ac4ee1aee8c 100644 (file)
@@ -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);
+}
index 1e6e9bf46f5e4907ce8bbf394847ca6514f2fb2e..212cb1eff50e14cd553a3e2905fa52ebfcfb6749 100644 (file)
@@ -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);
 }
index 741624ad8d4b402773c94a83c333cb318b2b973c..d54d8d4dc42553ace755c984a82f9bea4d618ee0 100644 (file)
@@ -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 */
index 4371ab5d523f9c7f3b372ef90ef221af791f912b..28f471d91e5b299724797cc154195c2f0aaf4a19 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <xfs/libxfs.h>
+#include <aio.h>
+#include <diskinfo.h>
 
 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);
+}
index 6aaea38261069f4b20b50077b60a4db569830add..2b2d59440ac88a5ebeba44e65c150391b1fa8bc8 100644 (file)
@@ -20,6 +20,7 @@
 #include <xfs/libxfs.h>
 #include <mntent.h>
 #include <sys/stat.h>
+#include <aio.h>
 #undef ustat
 #include <sys/ustat.h>
 #include <sys/mount.h>
@@ -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 (file)
index 0000000..c1d1712
--- /dev/null
@@ -0,0 +1,192 @@
+#include <xfs/libxfs.h>
+#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 */
+}
index 0d0f9d83c371c5f6e274fd31ab75a25acb96df25..24648c1762e30ea00750f5e52b8a1bb76b980be9 100644 (file)
@@ -20,7 +20,6 @@
 #include <xfs/xfs_log.h>
 #include <xfs/xfs_log_priv.h>
 
-#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);
index d9b7106eb46bc7520c9ec50d5179b5058de6c249..060ee188160daf8a7995f6fc3906458ea080a60a 100644 (file)
@@ -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
index 16d69ee5e4d4ac135349ca3cc400a70f3145d111..97ded19679af38689e8eb221ab381b6f1874308a 100644 (file)
@@ -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
 
index aee12046685542640d1b3ec5f996ddbbecaa9005..58894a759ecb7e1a15e6c7175ade19155ee0daf9 100644 (file)
@@ -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
 
index 8938c31eb177751977d203f03a53561cff8dbaea..5abe912b0adc16c1e77193ea8db069021d2fe942 100644 (file)
@@ -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
 
index 2edb2bc68c5ab678ed9fe8f6010bcdf2cf46cbe8..e8ad51c0de8d6b84860317b49c22e8a73f1847c3 100644 (file)
@@ -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 */
index 254cb49bb3cf52f21ea4d1e3c63fb2359a39fd22..2117bb4e284d093a70057e9401cba25877c53371 100644 (file)
@@ -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
index 0dc82ae44bc684452f823d63055cfee4835d1ed6..a6438a060077a2243b92dc5a5bc07ee1e65d39e3 100644 (file)
@@ -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;
index e8dce55d65d4250bb3bd8dd3e48e72ed83021987..7c06f52d76af2c04aeb8cf757691a90081ca378c 100644 (file)
@@ -22,6 +22,7 @@
 #include "protos.h"
 #include "err_protos.h"
 #include "pthread.h"
+#include "prefetch.h"
 #include <sys/resource.h>
 
 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();
+       }
 }
index c57a350b3b56a780b28d7d1268d7742877848502..bf11490ba2b38670e7fd15746473cb1bcb21e0b2 100644 (file)
@@ -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 (file)
index 0000000..cd198a5
--- /dev/null
@@ -0,0 +1,466 @@
+#include <libxfs.h>
+#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 (file)
index 0000000..10e83ed
--- /dev/null
@@ -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 */
index 2d60cbe2843fea85b7803e577498fe48b585e341..a85e5180da4c3bc9070ce78ef27fbb4cf933468b 100644 (file)
@@ -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)))
index 92c90ca7ff62b427141a6bc96f990abb70a8a4c2..505e21e837cb8752f979c4ad6a443d7b228fbc95 100644 (file)
@@ -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