]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Implement buffer and inode caching in libxfs, groundwork for a parallel version of...
authorNathan Scott <nathans@sgi.com>
Thu, 18 May 2006 15:52:04 +0000 (15:52 +0000)
committerNathan Scott <nathans@sgi.com>
Thu, 18 May 2006 15:52:04 +0000 (15:52 +0000)
Merge of master-melb:xfs-cmds:25967a by kenmcd.

13 files changed:
include/libxfs.h
include/libxlog.h
libxfs/init.c
libxfs/rdwr.c
libxfs/trans.c
libxfs/util.c
libxfs/xfs.h
libxfs/xfs_inode.c
libxfs/xfs_mount.c
mkfs/xfs_mkfs.c
repair/phase6.c
repair/scan.c
repair/xfs_repair.c

index 24d0173024b806603d395c7613e184864d46e806..e430d00b7f4d8e8e28fd7e7958500bcfd0670fd0 100644 (file)
 
 #include <xfs/platform_defs.h>
 
+#include "pthread.h"
+#include <xfs/list.h>
+#include <xfs/cache.h>
+
 #include <xfs/xfs_fs.h>
 #include <xfs/xfs_types.h>
 #include <xfs/xfs_arch.h>
@@ -97,6 +101,7 @@ typedef struct {
 
 extern char    *progname;
 extern int     libxfs_init (libxfs_init_t *);
+extern void    libxfs_destroy (void);
 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);
@@ -183,12 +188,16 @@ typedef struct xfs_mount {
 #define LIBXFS_MOUNT_32BITINOOPT       0x0008
 #define LIBXFS_MOUNT_COMPAT_ATTR       0x0010
 
+#define LIBXFS_IHASHSIZE(sbp)          (1<<16) /* tweak based on icount? */
+#define LIBXFS_BHASHSIZE(sbp)          (1<<16) /* ditto, on blocks used? */
+
 extern xfs_mount_t     *libxfs_mount (xfs_mount_t *, xfs_sb_t *,
                                dev_t, dev_t, dev_t, int);
 extern void    libxfs_mount_common (xfs_mount_t *, xfs_sb_t *);
 extern xfs_agnumber_t  libxfs_initialize_perag (xfs_mount_t *, xfs_agnumber_t);
 extern void    libxfs_umount (xfs_mount_t *);
 extern int     libxfs_rtmount_init (xfs_mount_t *);
+extern void    libxfs_rtmount_destroy (xfs_mount_t *);
 extern void    libxfs_alloc_compute_maxlevels (xfs_mount_t *);
 extern void    libxfs_bmap_compute_maxlevels (xfs_mount_t *, int);
 extern void    libxfs_ialloc_compute_maxlevels (xfs_mount_t *);
@@ -199,15 +208,24 @@ extern void       libxfs_trans_init (xfs_mount_t *);
  * Simple I/O interface
  */
 typedef struct xfs_buf {
-       xfs_daddr_t     b_blkno;
-       unsigned        b_bcount;
-       dev_t           b_dev;
-       void            *b_fsprivate;
-       void            *b_fsprivate2;
-       void            *b_fsprivate3;
-       char            *b_addr;
-       /* b_addr must be the last field */
+       struct cache_node       b_node;
+       unsigned int            b_flags;
+       xfs_daddr_t             b_blkno;
+       unsigned                b_bcount;
+       dev_t                   b_dev;
+       void                    *b_fsprivate;
+       void                    *b_fsprivate2;
+       void                    *b_fsprivate3;
+       char                    *b_addr;
 } xfs_buf_t;
+
+enum xfs_buf_flags_t { /* b_flags bits */
+       LIBXFS_B_EXIT           = 0x0001,       /* ==LIBXFS_EXIT_ON_FAILURE */
+       LIBXFS_B_DIRTY          = 0x0002,       /* buffer has been modified */
+       LIBXFS_B_STALE          = 0x0004,       /* buffer marked as invalid */
+       LIBXFS_B_UPTODATE       = 0x0008,       /* buffer is sync'd to disk */
+};
+
 #define XFS_BUF_PTR(bp)                        ((bp)->b_addr)
 #define xfs_buf_offset(bp, offset)     (XFS_BUF_PTR(bp) + (offset))
 #define XFS_BUF_ADDR(bp)               ((bp)->b_blkno)
@@ -226,13 +244,20 @@ typedef struct xfs_buf {
 #define XFS_BUF_FSPRIVATE3(bp,type)    ((type)(bp)->b_fsprivate3)
 #define XFS_BUF_SET_FSPRIVATE3(bp,val) (bp)->b_fsprivate3 = (void *)(val)
 
-extern xfs_buf_t       *libxfs_getbuf (dev_t, xfs_daddr_t, int);
-extern xfs_buf_t       *libxfs_readbuf (dev_t, xfs_daddr_t, int, int);
 extern xfs_buf_t       *libxfs_getsb (xfs_mount_t *, int);
+extern xfs_buf_t       *libxfs_readbuf (dev_t, xfs_daddr_t, int, int);
 extern int     libxfs_readbufr (dev_t, xfs_daddr_t, xfs_buf_t *, int, int);
 extern int     libxfs_writebuf (xfs_buf_t *, int);
+extern int     libxfs_writebufr (xfs_buf_t *);
 extern int     libxfs_writebuf_int (xfs_buf_t *, int);
+
+/* Buffer Cache Interfaces */
+extern struct cache    *libxfs_bcache;
+extern struct cache_operations libxfs_bcache_operations;
+extern void    libxfs_bcache_purge (void);
+extern xfs_buf_t       *libxfs_getbuf (dev_t, xfs_daddr_t, int);
 extern void    libxfs_putbuf (xfs_buf_t *);
+extern void    libxfs_purgebuf (xfs_buf_t *);
 
 #define LIBXFS_BREAD   0x1
 #define LIBXFS_BWRITE  0x2
@@ -289,6 +314,7 @@ extern int  libxfs_trans_reserve (xfs_trans_t *, uint,uint,uint,uint,uint);
 extern int     libxfs_trans_commit (xfs_trans_t *, uint, xfs_lsn_t *);
 extern void    libxfs_trans_cancel (xfs_trans_t *, int);
 extern void    libxfs_mod_sb (xfs_trans_t *, __int64_t);
+extern xfs_buf_t       *libxfs_trans_getsb (xfs_trans_t *, xfs_mount_t *, int);
 
 extern int     libxfs_trans_iget (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
                                uint, uint, struct xfs_inode **);
@@ -330,8 +356,8 @@ extern void *libxfs_realloc (void *, size_t);
 /*
  * Inode interface
  */
-struct xfs_inode_log_item;
 typedef struct xfs_inode {
+       struct cache_node       i_node;
        xfs_mount_t             *i_mount;       /* fs mount struct ptr */
        xfs_ino_t               i_ino;          /* inode number (agno/agino) */
        xfs_daddr_t             i_blkno;        /* blkno of inode buffer */
@@ -340,8 +366,8 @@ typedef struct xfs_inode {
        ushort                  i_boffset;      /* off of inode in buffer */
        xfs_ifork_t             *i_afp;         /* attribute fork pointer */
        xfs_ifork_t             i_df;           /* data fork */
-       struct xfs_trans        *i_transp;      /* ptr to owning transaction */
-       struct xfs_inode_log_item *i_itemp;     /* logging information */
+       xfs_trans_t             *i_transp;      /* ptr to owning transaction */
+       xfs_inode_log_item_t    *i_itemp;       /* logging information */
        unsigned int            i_delayed_blks; /* count of delay alloc blks */
        xfs_dinode_core_t       i_d;            /* most of ondisk inode */
 } xfs_inode_t;
@@ -363,12 +389,18 @@ extern void       libxfs_trans_inode_alloc_buf (xfs_trans_t *, xfs_buf_t *);
 
 extern void    libxfs_idata_realloc (xfs_inode_t *, int, int);
 extern void    libxfs_idestroy_fork (xfs_inode_t *, int);
-extern int     libxfs_iread (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
-                               xfs_inode_t **, xfs_daddr_t);
+extern int     libxfs_iformat (xfs_inode_t *, xfs_dinode_t *);
 extern void    libxfs_ichgtime (xfs_inode_t *, int);
 extern int     libxfs_iflush_int (xfs_inode_t *, xfs_buf_t *);
 extern int     libxfs_itobp (xfs_mount_t *, xfs_trans_t *, xfs_inode_t *,
                                xfs_dinode_t **, xfs_buf_t **, xfs_daddr_t);
+extern int     libxfs_iread (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
+                               xfs_inode_t *, xfs_daddr_t);
+
+/* Inode Cache Interfaces */
+extern struct cache    *libxfs_icache;
+extern struct cache_operations libxfs_icache_operations;
+extern void    libxfs_icache_purge (void);
 extern int     libxfs_iget (xfs_mount_t *, xfs_trans_t *, xfs_ino_t,
                                uint, xfs_inode_t **, xfs_daddr_t);
 extern void    libxfs_iput (xfs_inode_t *, uint);
index fcdbadcd9893acaa784cdf1660e6895bdf1636db..cef47cd5b459d7b5fdffb4090dd2543a66e0b420 100644 (file)
@@ -79,7 +79,7 @@ extern void xlog_warn(char *fmt,...);
 extern void xlog_exit(char *fmt,...);
 extern void xlog_panic(char *fmt,...);
 
-#define xlog_get_bp(log,bbs)   libxfs_getbuf(x.logdev, 0, (bbs))
+#define xlog_get_bp(log,bbs)   libxfs_getbuf(x.logdev, (xfs_daddr_t)-1, (bbs))
 #define xlog_put_bp(bp)                libxfs_putbuf(bp)
 #define xlog_bread(log,blkno,bbs,bp)   \
        (libxfs_readbufr(x.logdev,      \
index 0ec5415637b635390fea31e5d9e8175f33d4fab8..b5ae26edc7e709d2bc888ae2df9c1ca4ccf36645 100644 (file)
 
 char *progname = "libxfs";     /* default, changed by each tool */
 
+struct cache *libxfs_icache;   /* global inode cache */
+int libxfs_icache_size;                /* #buckets in icache */
+
+struct cache *libxfs_bcache;   /* global buffer cache */
+int libxfs_bcache_size;                /* #buckets in bcache */
+
+static void manage_zones(int); /* setup global zones */
+
 /*
  * dev_map - map open devices to fd.
  */
@@ -380,6 +388,13 @@ voldone:
        }
        if (needcd)
                chdir(curdir);
+       if (!libxfs_icache_size)
+               libxfs_icache_size = LIBXFS_IHASHSIZE(sbp);
+       libxfs_icache = cache_init(libxfs_icache_size,&libxfs_icache_operations);
+       if (!libxfs_bcache_size)
+               libxfs_bcache_size = LIBXFS_BHASHSIZE(sbp);
+       libxfs_bcache = cache_init(libxfs_bcache_size,&libxfs_bcache_operations);
+       manage_zones(0);
        rval = 1;
 done:
        if (dpath[0])
@@ -406,6 +421,7 @@ done:
 static void
 manage_zones(int release)
 {
+       extern xfs_zone_t       *xfs_buf_zone;
        extern xfs_zone_t       *xfs_ili_zone;
        extern xfs_zone_t       *xfs_inode_zone;
        extern xfs_zone_t       *xfs_ifork_zone;
@@ -417,6 +433,7 @@ manage_zones(int release)
        extern void             xfs_dir_startup();
 
        if (release) {  /* free zone allocation */
+               libxfs_free(xfs_buf_zone);
                libxfs_free(xfs_inode_zone);
                libxfs_free(xfs_ifork_zone);
                libxfs_free(xfs_dabuf_zone);
@@ -427,6 +444,7 @@ manage_zones(int release)
                return;
        }
        /* otherwise initialise zone allocation */
+       xfs_buf_zone = libxfs_zone_init(sizeof(xfs_buf_t), "xfs_buffer");
        xfs_inode_zone = libxfs_zone_init(sizeof(xfs_inode_t), "xfs_inode");
        xfs_ifork_zone = libxfs_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
        xfs_dabuf_zone = libxfs_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
@@ -456,7 +474,7 @@ rtmount_inodes(xfs_mount_t *mp)
        sbp = &mp->m_sb;
        if (sbp->sb_rbmino == NULLFSINO)
                return 0;
-       error = libxfs_iread(mp, NULL, sbp->sb_rbmino, &mp->m_rbmip, 0);
+       error = libxfs_iget(mp, NULL, sbp->sb_rbmino, 0, &mp->m_rbmip, 0);
        if (error) {
                fprintf(stderr,
                        _("%s: cannot read realtime bitmap inode (%d)\n"),
@@ -465,8 +483,9 @@ rtmount_inodes(xfs_mount_t *mp)
        }
        ASSERT(mp->m_rbmip != NULL);
        ASSERT(sbp->sb_rsumino != NULLFSINO);
-       error = libxfs_iread(mp, NULL, sbp->sb_rsumino, &mp->m_rsumip, 0);
+       error = libxfs_iget(mp, NULL, sbp->sb_rsumino, 0, &mp->m_rsumip, 0);
        if (error) {
+               libxfs_iput(mp->m_rbmip, 0);
                fprintf(stderr,
                        _("%s: cannot read realtime summary inode (%d)\n"),
                        progname, error);
@@ -556,7 +575,6 @@ libxfs_mount(
        mp->m_flags = (LIBXFS_MOUNT_32BITINODES|LIBXFS_MOUNT_32BITINOOPT);
        mp->m_sb = *sb;
        sbp = &(mp->m_sb);
-       manage_zones(0);
 
        libxfs_mount_common(mp, sb);
 
@@ -675,7 +693,7 @@ libxfs_mount(
         * mkfs calls mount before the root inode is allocated.
         */
        if ((flags & LIBXFS_MOUNT_ROOTINOS) && sbp->sb_rootino != NULLFSINO) {
-               error = libxfs_iread(mp, NULL, sbp->sb_rootino,
+               error = libxfs_iget(mp, NULL, sbp->sb_rootino, 0,
                                &mp->m_rootip, 0);
                if (error) {
                        fprintf(stderr, _("%s: cannot read root inode (%d)\n"),
@@ -685,18 +703,33 @@ libxfs_mount(
                }
                ASSERT(mp->m_rootip != NULL);
        }
-       if ((flags & LIBXFS_MOUNT_ROOTINOS) && rtmount_inodes(mp))
+       if ((flags & LIBXFS_MOUNT_ROOTINOS) && rtmount_inodes(mp)) {
+               libxfs_iput(mp->m_rootip, 0);
                return NULL;
+       }
        return mp;
 }
 
+void
+libxfs_rtmount_destroy(xfs_mount_t *mp)
+{
+       if (mp->m_rsumip)
+               libxfs_iput(mp->m_rsumip, 0);
+       if (mp->m_rbmip)
+               libxfs_iput(mp->m_rbmip, 0);
+       mp->m_rsumip = mp->m_rbmip = NULL;
+}
+
 /*
  * Release any resource obtained during a mount.
  */
 void
 libxfs_umount(xfs_mount_t *mp)
 {
-       manage_zones(1);
+       libxfs_rtmount_destroy(mp);
+       libxfs_icache_purge();
+       libxfs_bcache_purge();
+
        if (mp->m_perag) {
                int     agno;
                for (agno = 0; agno < mp->m_maxagi; agno++) {
@@ -706,3 +739,14 @@ libxfs_umount(xfs_mount_t *mp)
                free(mp->m_perag);
        }
 }
+
+/*
+ * Release any global resources used by libxfs.
+ */
+void
+libxfs_destroy(void)
+{
+       manage_zones(1);
+       cache_destroy(libxfs_icache);
+       cache_destroy(libxfs_bcache);
+}
index 2b26ccbdf4e8c4f3daf5682908ea11ec1bc4d396..501efff1b274b1249c013f9133fc9fd23b7aa9b2 100644 (file)
@@ -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
 #define BDSTRAT_SIZE   (256 * 1024)
 #define min(x, y)      ((x) < (y) ? (x) : (y))
 
+static inline void *
+libxfs_memalign(size_t size)
+{
+       static size_t   pagealign;
+
+       if (!pagealign)
+               pagealign = getpagesize();
+       return memalign(pagealign, size);
+}
+
 void
 libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len)
 {
@@ -33,7 +43,7 @@ libxfs_device_zero(dev_t dev, xfs_daddr_t start, uint len)
        int             fd;
 
        zsize = min(BDSTRAT_SIZE, BBTOB(len));
-       if ((z = memalign(getpagesize(), zsize)) == NULL) {
+       if ((z = libxfs_memalign(zsize)) == NULL) {
                fprintf(stderr,
                        _("%s: %s can't memalign %d bytes: %s\n"),
                        progname, __FUNCTION__, (int)zsize, strerror(errno));
@@ -121,13 +131,10 @@ libxfs_log_clear(
        len = ((version == 2) && sunit) ? BTOBB(sunit) : 2;
        len = MAX(len, 2);
        buf = libxfs_getbuf(device, start, len);
-       if (!buf)
-               return -1;
        libxfs_log_header(XFS_BUF_PTR(buf),
                          fs_uuid, version, sunit, fmt, next, buf);
-       if (libxfs_writebuf(buf, 0))
-               return -1;
-
+       libxfs_writebufr(buf);
+       libxfs_putbuf(buf);
        return 0;
 }
 
@@ -186,46 +193,125 @@ libxfs_log_header(
        return BBTOB(len);
 }
 
+xfs_buf_t *
+libxfs_getsb(xfs_mount_t *mp, int flags)
+{
+       return libxfs_readbuf(mp->m_dev, XFS_SB_DADDR,
+                               XFS_FSS_TO_BB(mp, 1), flags);
+}
+
 
 /*
- * Simple I/O interface
+ * Simple I/O (buffer cache) interface
  */
 
+xfs_zone_t     *xfs_buf_zone;
+
+typedef struct {
+       dev_t           device;
+       xfs_daddr_t     blkno;
+       unsigned int    count;
+} xfs_bufkey_t;
+
+static unsigned int
+libxfs_bhash(cache_key_t key, unsigned int hashsize)
+{
+       return ((unsigned int)((xfs_bufkey_t *)key)->blkno) % hashsize;
+}
+
+static int
+libxfs_bcompare(struct cache_node *node, cache_key_t key)
+{
+       xfs_buf_t       *bp = (xfs_buf_t *)node;
+       xfs_bufkey_t    *bkey = (xfs_bufkey_t *)key;
+
+#ifdef IO_BCOMPARE_CHECK
+       if (bp->b_dev == bkey->device &&
+           bp->b_blkno == bkey->blkno &&
+           bp->b_bcount != bkey->count)
+               fprintf(stderr, "Badness in key lookup (length)\n"
+                       "bp=(bno %llu, len %u bb) key=(bno %llu, len %u bbs)\n",
+                       (unsigned long long)bp->b_blkno, (int)bp->b_bcount,
+                       (unsigned long long)bkey->blkno, (int)bkey->count);
+#endif
+
+       return (bp->b_dev == bkey->device &&
+               bp->b_blkno == bkey->blkno &&
+               bp->b_bcount == bkey->count);
+}
+
+void
+libxfs_bprint(xfs_buf_t *bp)
+{
+       fprintf(stderr, "Buffer 0x%p blkno=%llu bytes=%u flags=0x%x count=%u\n",
+               bp, (unsigned long long)bp->b_blkno, (unsigned)bp->b_bcount,
+               bp->b_flags, bp->b_node.cn_count);
+}
+
 xfs_buf_t *
 libxfs_getbuf(dev_t device, xfs_daddr_t blkno, int len)
 {
-       xfs_buf_t       *buf;
-       size_t          total;
+       xfs_buf_t       *bp;
+       xfs_bufkey_t    key;
+       unsigned int    bytes = BBTOB(len);
 
-       total = sizeof(xfs_buf_t) + BBTOB(len);
-       if ((buf = calloc(total, 1)) == NULL) {
-               fprintf(stderr, _("%s: buf calloc failed (%ld bytes): %s\n"),
-                       progname, (long)total, strerror(errno));
-               exit(1);
-       }
-       /* by default, we allocate buffer directly after the header */
-       buf->b_blkno = blkno;
-       buf->b_bcount = BBTOB(len);
-       buf->b_dev = device;
-       buf->b_addr = (char *)(&buf->b_addr + 1);       /* must be last field */
+       key.device = device;
+       key.blkno = blkno;
+       key.count = bytes;
+
+       if (cache_node_get(libxfs_bcache, &key, (struct cache_node **)&bp)) {
 #ifdef IO_DEBUG
-       fprintf(stderr, "getbuf allocated %ubytes, blkno=%llu(%llu), %p\n",
-               BBTOB(len), BBTOOFF64(blkno), blkno, buf);
+               fprintf(stderr, "%s: allocated buffer, key=%llu(%llu), %p\n",
+                       __FUNCTION__, BBTOB(len), BBTOOFF64(blkno), blkno, buf);
 #endif
+               bp->b_flags = 0;
+               bp->b_blkno = blkno;
+               bp->b_bcount = bytes;
+               bp->b_dev = device;
+               if (!(bp->b_addr = libxfs_memalign(bytes))) {
+                       fprintf(stderr,
+                               _("%s: %s can't memalign %d bytes: %s\n"),
+                               progname, __FUNCTION__, (int)bytes,
+                               strerror(errno));
+                       exit(1);
+               }
+       }
+       return bp;
+}
+
+void
+libxfs_putbuf(xfs_buf_t *bp)
+{
+       cache_node_put((struct cache_node *)bp);
+}
+
+void
+libxfs_purgebuf(xfs_buf_t *bp)
+{
+       xfs_bufkey_t    key;
+
+       key.device = bp->b_dev;
+       key.blkno = bp->b_blkno;
+       key.count = bp->b_bcount;
+
+       cache_node_purge(libxfs_bcache, &key, (struct cache_node *)bp);
+}
 
-       return(buf);
+static struct cache_node *
+libxfs_balloc(void)
+{
+       return libxfs_zone_zalloc(xfs_buf_zone);
 }
 
 int
-libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *buf, int len, int flags)
+libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *bp, int len, int flags)
 {
        int     fd = libxfs_device_to_fd(dev);
+       int     bytes = BBTOB(len);
 
-       buf->b_dev = dev;
-       buf->b_blkno = blkno;
-       ASSERT(BBTOB(len) <= buf->b_bcount);
+       ASSERT(BBTOB(len) <= bp->b_bcount);
 
-       if (pread64(fd, buf->b_addr, BBTOB(len), BBTOOFF64(blkno)) < 0) {
+       if (pread64(fd, bp->b_addr, bytes, BBTOOFF64(blkno)) < 0) {
                fprintf(stderr, _("%s: read failed: %s\n"),
                        progname, strerror(errno));
                if (flags & LIBXFS_EXIT_ON_FAILURE)
@@ -234,108 +320,135 @@ libxfs_readbufr(dev_t dev, xfs_daddr_t blkno, xfs_buf_t *buf, int len, int flags
        }
 #ifdef IO_DEBUG
        fprintf(stderr, "readbufr read %ubytes, blkno=%llu(%llu), %p\n",
-               BBTOB(len), BBTOOFF64(blkno), blkno, buf);
+               bytes, BBTOOFF64(blkno), blkno, bp);
 #endif
+       if (bp->b_dev == dev &&
+           bp->b_blkno == blkno &&
+           bp->b_bcount == bytes)
+               bp->b_flags |= LIBXFS_B_UPTODATE;
        return 0;
 }
 
 xfs_buf_t *
 libxfs_readbuf(dev_t dev, xfs_daddr_t blkno, int len, int flags)
 {
-       xfs_buf_t       *buf;
+       xfs_buf_t       *bp;
        int             error;
 
-       buf = libxfs_getbuf(dev, blkno, len);
-       error = libxfs_readbufr(dev, blkno, buf, len, flags);
-       if (error) {
-               libxfs_putbuf(buf);
-               return NULL;
+       bp = libxfs_getbuf(dev, blkno, len);
+       if (!(bp->b_flags & (LIBXFS_B_UPTODATE|LIBXFS_B_DIRTY))) {
+               error = libxfs_readbufr(dev, blkno, bp, len, flags);
+               if (error) {
+                       libxfs_putbuf(bp);
+                       return NULL;
+               }
        }
-       return buf;
-}
-
-xfs_buf_t *
-libxfs_getsb(xfs_mount_t *mp, int flags)
-{
-       return libxfs_readbuf(mp->m_dev, XFS_SB_DADDR,
-                               XFS_FSB_TO_BB(mp, 1), flags);
+       return bp;
 }
 
 int
-libxfs_writebuf_int(xfs_buf_t *buf, int flags)
+libxfs_writebufr(xfs_buf_t *bp)
 {
        int     sts;
-       int     fd = libxfs_device_to_fd(buf->b_dev);
+       int     fd = libxfs_device_to_fd(bp->b_dev);
 
-#ifdef IO_DEBUG
-       fprintf(stderr, "writing %ubytes at blkno=%llu(%llu), %p\n",
-               buf->b_bcount, BBTOOFF64(buf->b_blkno), buf->b_blkno, buf);
-#endif
-       sts = pwrite64(fd, buf->b_addr, buf->b_bcount, BBTOOFF64(buf->b_blkno));
+       sts = pwrite64(fd, bp->b_addr, bp->b_bcount, BBTOOFF64(bp->b_blkno));
        if (sts < 0) {
                fprintf(stderr, _("%s: pwrite64 failed: %s\n"),
                        progname, strerror(errno));
-               if (flags & LIBXFS_EXIT_ON_FAILURE)
+               if (bp->b_flags & LIBXFS_B_EXIT)
                        exit(1);
                return errno;
        }
-       else if (sts != buf->b_bcount) {
+       else if (sts != bp->b_bcount) {
                fprintf(stderr, _("%s: error - wrote only %d of %d bytes\n"),
-                       progname, sts, buf->b_bcount);
-               if (flags & LIBXFS_EXIT_ON_FAILURE)
+                       progname, sts, bp->b_bcount);
+               if (bp->b_flags & LIBXFS_B_EXIT)
                        exit(1);
                return EIO;
        }
+#ifdef IO_DEBUG
+       fprintf(stderr, "writebufr wrote %ubytes, blkno=%llu(%llu), %p\n",
+               bp->b_bcount, BBTOOFF64(bp->b_blkno), bp->b_blkno, bp);
+#endif
+       bp->b_flags |= LIBXFS_B_UPTODATE;
+       bp->b_flags &= ~(LIBXFS_B_DIRTY | LIBXFS_B_EXIT);
        return 0;
 }
 
 int
-libxfs_writebuf(xfs_buf_t *buf, int flags)
+libxfs_writebuf_int(xfs_buf_t *bp, int flags)
 {
-       int error = libxfs_writebuf_int(buf, flags);
-       libxfs_putbuf(buf);
-       return error;
+       bp->b_flags |= (LIBXFS_B_DIRTY | flags);
+       return 0;
+}
+
+int
+libxfs_writebuf(xfs_buf_t *bp, int flags)
+{
+       bp->b_flags |= (LIBXFS_B_DIRTY | flags);
+       libxfs_putbuf(bp);
+       return 0;
 }
 
 void
-libxfs_iomove(xfs_buf_t *buf, uint boff, int len, void *data, int flags)
+libxfs_iomove(xfs_buf_t *bp, uint boff, int len, void *data, int flags)
 {
-       if (boff + len > buf->b_bcount)
+#ifdef IO_DEBUG
+       if (boff + len > bp->b_bcount) {
+               fprintf(stderr, "Badness, iomove out of range!\n"
+                       "bp=(bno %llu, bytes %u) range=(boff %u, bytes %u)\n",
+                       bp->b_blkno, bp->b_bcount, boff, len);
                abort();
-
+       }
+#endif
        switch (flags) {
        case LIBXFS_BZERO:
-               memset(buf->b_addr + boff, 0, len);
+               memset(bp->b_addr + boff, 0, len);
                break;
        case LIBXFS_BREAD:
-               memcpy(data, buf->b_addr + boff, len);
+               memcpy(data, bp->b_addr + boff, len);
                break;
        case LIBXFS_BWRITE:
-               memcpy(buf->b_addr + boff, data, len);
+               memcpy(bp->b_addr + boff, data, len);
                break;
        }
 }
 
-void
-libxfs_putbuf(xfs_buf_t *buf)
+static void
+libxfs_brelse(struct cache_node *node)
 {
-       if (buf != NULL) {
-               xfs_buf_log_item_t      *bip;
-               extern xfs_zone_t       *xfs_buf_item_zone;
-
-               bip = XFS_BUF_FSPRIVATE(buf, xfs_buf_log_item_t *);
-
+       xfs_buf_t               *bp = (xfs_buf_t *)node;
+       xfs_buf_log_item_t      *bip;
+       extern xfs_zone_t       *xfs_buf_item_zone;
+
+       if (bp != NULL) {
+               if (bp->b_flags & LIBXFS_B_DIRTY)
+                       libxfs_writebufr(bp);
+               bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
                if (bip)
                    libxfs_zone_free(xfs_buf_item_zone, bip);
-#ifdef IO_DEBUG
-               fprintf(stderr, "putbuf released %ubytes, %p\n",
-                       buf->b_bcount, buf);
-#endif
-               free(buf);
-               buf = NULL;
+               free(bp->b_addr);
+               bp->b_addr = NULL;
+               bp->b_flags = 0;
+               free(bp);
+               bp = NULL;
        }
 }
 
+void
+libxfs_bcache_purge(void)
+{
+       cache_purge(libxfs_bcache);
+}
+
+struct cache_operations libxfs_bcache_operations = {
+       /* .hash */     libxfs_bhash,
+       /* .alloc */    libxfs_balloc,
+       /* .relse */    libxfs_brelse,
+       /* .compare */  libxfs_bcompare,
+};
+
 
 /*
  * Simple memory interface
@@ -406,8 +519,7 @@ libxfs_malloc(size_t size)
                exit(1);
        }
 #ifdef MEM_DEBUG
-       fprintf(stderr, "## calloc'd item %p size %d bytes\n",
-               ptr, size);
+       fprintf(stderr, "## calloc'd item %p size %d bytes\n", ptr, size);
 #endif
        return ptr;
 }
@@ -416,8 +528,7 @@ void
 libxfs_free(void *ptr)
 {
 #ifdef MEM_DEBUG
-       fprintf(stderr, "## freed item %p\n",
-               ptr);
+       fprintf(stderr, "## freed item %p\n", ptr);
 #endif
        if (ptr != NULL) {
                free(ptr);
@@ -444,21 +555,62 @@ libxfs_realloc(void *ptr, size_t size)
 }
 
 
+/*
+ * Inode cache interfaces
+ */
+
+extern xfs_zone_t      *xfs_ili_zone;
+extern xfs_zone_t      *xfs_inode_zone;
+
+static unsigned int
+libxfs_ihash(cache_key_t key, unsigned int hashsize)
+{
+       return ((unsigned int)*(xfs_ino_t *)key) % hashsize;
+}
+
+static int
+libxfs_icompare(struct cache_node *node, cache_key_t key)
+{
+       xfs_inode_t     *ip = (xfs_inode_t *)node;
+
+       return (ip->i_ino == *(xfs_ino_t *)key);
+}
+
 int
 libxfs_iget(xfs_mount_t *mp, xfs_trans_t *tp, xfs_ino_t ino, uint lock_flags,
                xfs_inode_t **ipp, xfs_daddr_t bno)
 {
        xfs_inode_t     *ip;
-       int             error;
+       int             error = 0;
 
-       error = libxfs_iread(mp, tp, ino, &ip, bno);
-       if (error)
-               return error;
+       if (cache_node_get(libxfs_icache, &ino, (struct cache_node **)&ip)) {
+#ifdef INO_DEBUG
+               fprintf(stderr, "%s: allocated inode, ino=%llu(%llu), %p\n",
+                       __FUNCTION__, (unsigned long long)ino, bno, ip);
+#endif
+               if ((error = libxfs_iread(mp, tp, ino, ip, bno))) {
+                       cache_node_purge(libxfs_icache, &ino,
+                                       (struct cache_node *)ip);
+                       ip = NULL;
+               }
+       }
        *ipp = ip;
-       return 0;
+       return error;
 }
 
 void
+libxfs_iput(xfs_inode_t *ip, uint lock_flags)
+{
+       cache_node_put((struct cache_node *)ip);
+}
+
+static struct cache_node *
+libxfs_ialloc(void)
+{
+       return libxfs_zone_zalloc(xfs_inode_zone);
+}
+
+static void
 libxfs_idestroy(xfs_inode_t *ip)
 {
        switch (ip->i_d.di_mode & S_IFMT) {
@@ -472,15 +624,12 @@ libxfs_idestroy(xfs_inode_t *ip)
                libxfs_idestroy_fork(ip, XFS_ATTR_FORK);
 }
 
-void
-libxfs_iput(xfs_inode_t *ip, uint lock_flags)
+static void
+libxfs_irelse(struct cache_node *node)
 {
-       extern xfs_zone_t       *xfs_ili_zone;
-       extern xfs_zone_t       *xfs_inode_zone;
+       xfs_inode_t     *ip = (xfs_inode_t *)node;
 
        if (ip != NULL) {
-
-               /* free attached inode log item */
                if (ip->i_itemp)
                        libxfs_zone_free(xfs_ili_zone, ip->i_itemp);
                ip->i_itemp = NULL;
@@ -490,22 +639,15 @@ libxfs_iput(xfs_inode_t *ip, uint lock_flags)
        }
 }
 
-/*
- * libxfs_mod_sb can be used to copy arbitrary changes to the
- * in-core superblock into the superblock buffer to be logged.
- *
- * In user-space, we simply convert to big-endian, and write the
- * the whole superblock - the in-core changes have all been made
- * already.
- */
 void
-libxfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
+libxfs_icache_purge(void)
 {
-       xfs_buf_t       *bp;
-       xfs_mount_t     *mp;
-
-       mp = tp->t_mountp;
-       bp = libxfs_getbuf(mp->m_dev, XFS_SB_DADDR, 1);
-       libxfs_xlate_sb(XFS_BUF_PTR(bp), &mp->m_sb, -1, XFS_SB_ALL_BITS);
-       libxfs_writebuf(bp, LIBXFS_EXIT_ON_FAILURE);
+       cache_purge(libxfs_icache);
 }
+
+struct cache_operations libxfs_icache_operations = {
+       /* .hash */     libxfs_ihash,
+       /* .alloc */    libxfs_ialloc,
+       /* .relse */    libxfs_irelse,
+       /* .compare */  libxfs_icompare,
+};
index c72497877743a615387d482c3c44dd1e97ec0ec5..33c24ac81914da65cc101550211ece2b8d466573 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2001,2005-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -113,9 +113,9 @@ libxfs_trans_iget(
        xfs_inode_log_item_t    *iip;
 
        if (tp == NULL)
-               return libxfs_iread(mp, tp, ino, ipp, 0);
+               return libxfs_iget(mp, tp, ino, lock_flags, ipp, 0);
 
-       error = libxfs_iread(mp, tp, ino, &ip, 0);
+       error = libxfs_iget(mp, tp, ino, lock_flags, &ip, 0);
        if (error)
                return error;
        ASSERT(ip != NULL);
@@ -310,14 +310,14 @@ libxfs_trans_brelse(
                bip->bli_recur--;
                return;
        }
-       /* If dirty, can't release till transaction committed */
-       if (lidp->lid_flags & XFS_LID_DIRTY) {
+       /* If dirty/stale, can't release till transaction committed */
+       if (bip->bli_flags & XFS_BLI_STALE)
+               return;
+       if (lidp->lid_flags & XFS_LID_DIRTY)
                return;
-       }
        xfs_trans_free_item(tp, lidp);
-       if (bip->bli_flags & XFS_BLI_HOLD) {
+       if (bip->bli_flags & XFS_BLI_HOLD)
                bip->bli_flags &= ~XFS_BLI_HOLD;
-       }
        XFS_BUF_SET_FSPRIVATE2(bp, NULL);
        libxfs_putbuf(bp);
 }
@@ -339,7 +339,12 @@ libxfs_trans_binval(
        bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
        lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip);
        ASSERT(lidp != NULL);
-       bip->bli_flags &= ~(XFS_BLI_DIRTY);
+       if (bip->bli_flags & XFS_BLI_STALE)
+               return;
+       XFS_BUF_UNDELAYWRITE(bp);
+       XFS_BUF_STALE(bp);
+       bip->bli_flags |= XFS_BLI_STALE;
+       bip->bli_flags &= ~XFS_BLI_DIRTY;
        bip->bli_format.blf_flags &= ~XFS_BLI_INODE_BUF;
        bip->bli_format.blf_flags |= XFS_BLI_CANCEL;
        lidp->lid_flags |= XFS_LID_DIRTY;
@@ -426,6 +431,49 @@ libxfs_trans_get_buf(
        return bp;
 }
 
+xfs_buf_t *
+libxfs_trans_getsb(
+       xfs_trans_t             *tp,
+       xfs_mount_t             *mp,
+       int                     flags)
+{
+       xfs_buf_t               *bp;
+       xfs_buf_log_item_t      *bip;
+       xfs_buftarg_t           bdev;
+       int                     len;
+
+       if (tp == NULL)
+               return libxfs_getsb(mp, flags);
+
+       bdev.dev = mp->m_dev;
+       len = XFS_FSS_TO_BB(mp, 1);
+       if (tp->t_items.lic_next == NULL)
+               bp = xfs_trans_buf_item_match(tp, &bdev, XFS_SB_DADDR, len);
+       else
+               bp = xfs_trans_buf_item_match_all(tp, &bdev, XFS_SB_DADDR, len);
+       if (bp != NULL) {
+               ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
+               bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+               ASSERT(bip != NULL);
+               bip->bli_recur++;
+               return bp;
+       }
+
+       bp = libxfs_getsb(mp, flags);
+#ifdef XACT_DEBUG
+       fprintf(stderr, "trans_get_sb buffer %p, transaction %p\n", bp, tp);
+#endif
+
+       xfs_buf_item_init(bp, mp);
+       bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
+       bip->bli_recur = 0;
+       xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
+
+       /* initialize b_fsprivate2 so we can find it incore */
+       XFS_BUF_SET_FSPRIVATE2(bp, tp);
+       return bp;
+}
+
 int
 libxfs_trans_read_buf(
        xfs_mount_t             *mp,
@@ -433,19 +481,16 @@ libxfs_trans_read_buf(
        dev_t                   dev,
        xfs_daddr_t             blkno,
        int                     len,
-       uint                    f,
+       uint                    flags,
        xfs_buf_t               **bpp)
 {
        xfs_buf_t               *bp;
        xfs_buf_log_item_t      *bip;
-       int                     error;
        xfs_buftarg_t           bdev;
 
        if (tp == NULL) {
-               bp = libxfs_getbuf(mp->m_dev, blkno, len);
-               error = libxfs_readbufr(dev, blkno, bp, len, 0);
-               *bpp = bp;
-               return error;
+               *bpp = libxfs_readbuf(dev, blkno, len, flags);
+               return 0;
        }
 
        bdev.dev = dev;
@@ -462,12 +507,7 @@ libxfs_trans_read_buf(
                return 0;
        }
 
-       bp = libxfs_getbuf(mp->m_dev, blkno, len);
-       error = libxfs_readbufr(dev, blkno, bp, len, 0);
-       if (error) {
-               *bpp = NULL;
-               return error;
-       }
+       bp = libxfs_readbuf(dev, blkno, len, flags);
 #ifdef XACT_DEBUG
        fprintf(stderr, "trans_read_buf buffer %p, transaction %p\n", bp, tp);
 #endif
@@ -572,7 +612,7 @@ inode_item_done(
        ip->i_transp = NULL;    /* disassociate from transaction */
        XFS_BUF_SET_FSPRIVATE(bp, NULL);        /* remove log item */
        XFS_BUF_SET_FSPRIVATE2(bp, NULL);       /* remove xact ptr */
-       libxfs_writebuf_int(bp, 0);
+       libxfs_writebuf(bp, 0);
 #ifdef XACT_DEBUG
        fprintf(stderr, "flushing dirty inode %llu, buffer %p (hold=%u)\n",
                        ip->i_ino, bp, hold);
@@ -582,8 +622,7 @@ inode_item_done(
                return;
        }
        else {
-               /*libxfs_iput(iip->ili_inode, 0);       - nathans TODO? */
-               libxfs_putbuf(bp);
+               libxfs_iput(iip->ili_inode, 0);
        }
 
 ili_done:
@@ -608,12 +647,13 @@ buf_item_done(
        XFS_BUF_SET_FSPRIVATE2(bp, NULL);       /* remove xact ptr */
 
        hold = (bip->bli_flags & XFS_BLI_HOLD);
-       if (bip->bli_flags & XFS_BLI_DIRTY) {
+       if (bip->bli_flags & (XFS_BLI_DIRTY|XFS_BLI_STALE)) {
 #ifdef XACT_DEBUG
-               fprintf(stderr, "flushing dirty buffer %p (hold=%d)\n",
+               fprintf(stderr, "flushing/staling buffer %p (hold=%d)\n",
                        bp, hold);
 #endif
-               libxfs_writebuf_int(bp, 0);
+               if (bip->bli_flags & XFS_BLI_DIRTY)
+                       libxfs_writebuf_int(bp, 0);
                if (hold)
                        bip->bli_flags &= ~XFS_BLI_HOLD;
                else
index 8d55b87990d23fdcca6292f17452b9fb4f76fa3b..bd932be87ecb95a8f63cfda911f25952260af860 100644 (file)
@@ -50,6 +50,61 @@ libxfs_ichgtime(xfs_inode_t *ip, int flags)
        }
 }
 
+/*
+ * Given a mount structure and an inode number, return a pointer
+ * to a newly allocated in-core inode coresponding to the given
+ * inode number.
+ *
+ * Initialize the inode's attributes and extent pointers if it
+ * already has them (it will not if the inode has no links).
+ */
+int
+libxfs_iread(
+       xfs_mount_t     *mp,
+       xfs_trans_t     *tp,
+       xfs_ino_t       ino,
+       xfs_inode_t     *ip,
+       xfs_daddr_t     bno)
+{
+       xfs_buf_t       *bp;
+       xfs_dinode_t    *dip;
+       int             error;
+
+       ip->i_ino = ino;
+       ip->i_mount = mp;
+       if ((error = xfs_itobp(mp, tp, ip, &dip, &bp, bno)))
+               return error;
+       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
+               xfs_trans_brelse(tp, bp);
+               return EINVAL;
+       }
+       if (dip->di_core.di_mode) {
+               xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
+                                       &(ip->i_d), 1);
+               if ((error = xfs_iformat(ip, dip))) {
+                       xfs_trans_brelse(tp, bp);
+                       return error;
+               }
+       } else {
+               ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
+               ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
+               ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
+               ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
+               ip->i_d.di_mode = 0;
+               ip->i_df.if_ext_max =
+                       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
+       }
+       if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
+               ip->i_d.di_nlink = ip->i_d.di_onlink;
+               ip->i_d.di_onlink = 0;
+               ip->i_d.di_projid = 0;
+       }
+       ip->i_delayed_blks = 0;
+       XFS_BUF_SET_REF(bp, XFS_INO_REF);
+       xfs_trans_brelse(tp, bp);
+       return 0;
+}
+
 /*
  * Allocate an inode on disk and return a copy of it's in-core version.
  * Set mode, nlink, and rdev appropriately within the inode.
index ed87c7a5648d13cca329fc464daee9bf2c39f068..d9b7106eb46bc7520c9ec50d5179b5058de6c249 100644 (file)
 #define xfs_initialize_perag           libxfs_initialize_perag
 #define xfs_rtmount_init               libxfs_rtmount_init
 #define xfs_alloc_fix_freelist         libxfs_alloc_fix_freelist
-#define xfs_iread                      libxfs_iread
 #define xfs_idata_realloc              libxfs_idata_realloc
 #define xfs_idestroy_fork              libxfs_idestroy_fork
+#define xfs_iread                      libxfs_iread
 #define xfs_itobp                      libxfs_itobp
+#define xfs_iformat                    libxfs_iformat
 #define xfs_ichgtime                   libxfs_ichgtime
 #define xfs_bmapi                      libxfs_bmapi
 #define xfs_bmap_finish                        libxfs_bmap_finish
 #define xfs_trans_alloc                        libxfs_trans_alloc
 #define xfs_trans_commit               libxfs_trans_commit
 #define xfs_trans_cancel               libxfs_trans_cancel
-#define xfs_trans_mod_sb               libxfs_trans_mod_sb
 #define xfs_trans_reserve              libxfs_trans_reserve
+#define xfs_trans_getsb                        libxfs_trans_getsb
+#define xfs_trans_mod_sb               libxfs_trans_mod_sb
 #define xfs_trans_get_buf              libxfs_trans_get_buf
 #define xfs_trans_log_buf              libxfs_trans_log_buf
 #define xfs_trans_read_buf             libxfs_trans_read_buf
 #define XFS_BUF_LOCK                   0
 #define XFS_BUF_MAPPED                 0
 #define XFS_BUF_TRYLOCK                        0
-#define XFS_BUF_ISDONE(bp)             0
 #define XFS_BUF_GETERROR(bp)           0
-#define XFS_BUF_DONE(bp)               ((void) 0)
-#define XFS_BUF_STALE(bp)              ((void) 0)
-#define XFS_BUF_UNDELAYWRITE(bp)       ((void) 0)
+#define XFS_BUF_DONE(bp)               ((bp)->b_flags |= LIBXFS_B_UPTODATE)
+#define XFS_BUF_ISDONE(bp)             ((bp)->b_flags & LIBXFS_B_UPTODATE)
+#define XFS_BUF_STALE(bp)              ((bp)->b_flags |= LIBXFS_B_STALE)
+#define XFS_BUF_UNDELAYWRITE(bp)       ((bp)->b_flags &= ~LIBXFS_B_DIRTY)
 #define XFS_BUF_SET_REF(a,b)           ((void) 0)
 #define XFS_BUF_SET_VTYPE(a,b)         ((void) 0)
 #define XFS_BUF_SET_VTYPE_REF(a,b,c)   ((void) 0)
@@ -420,6 +422,8 @@ static inline int xfs_btree_readahead (xfs_btree_cur_t *cur, int lev, int lr)
 /* xfs_inode.c */
 int  xfs_ialloc (xfs_trans_t *, xfs_inode_t *, mode_t, nlink_t, xfs_dev_t, cred_t *,
                xfs_prid_t, int, xfs_buf_t **, boolean_t *, xfs_inode_t **);
+int xfs_iread (xfs_mount_t *, xfs_trans_t *, xfs_ino_t, xfs_inode_t *,
+               xfs_daddr_t);
 int  xfs_iread_extents (xfs_trans_t *, xfs_inode_t *, int);
 int  xfs_imap (xfs_mount_t *, xfs_trans_t *, xfs_ino_t, xfs_imap_t *, uint);
 int  xfs_iextents_copy (xfs_inode_t *, xfs_bmbt_rec_t *, int);
index a4586128621086107d2b7638d0f4c885535d6653..844b9baaa7ffe3a249f9aeba4eb2efa598db5bb3 100644 (file)
@@ -605,172 +605,6 @@ xfs_xlate_dinode_core(
        INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
 }
 
-/*
- * Given a mount structure and an inode number, return a pointer
- * to a newly allocated in-core inode coresponding to the given
- * inode number.
- *
- * Initialize the inode's attributes and extent pointers if it
- * already has them (it will not if the inode has no links).
- */
-int
-xfs_iread(
-       xfs_mount_t     *mp,
-       xfs_trans_t     *tp,
-       xfs_ino_t       ino,
-       xfs_inode_t     **ipp,
-       xfs_daddr_t     bno)
-{
-       xfs_buf_t       *bp;
-       xfs_dinode_t    *dip;
-       xfs_inode_t     *ip;
-       int             error;
-
-       ASSERT(xfs_inode_zone != NULL);
-
-       ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
-       ip->i_ino = ino;
-       ip->i_mount = mp;
-
-       /*
-        * Get pointer's to the on-disk inode and the buffer containing it.
-        * If the inode number refers to a block outside the file system
-        * then xfs_itobp() will return NULL.  In this case we should
-        * return NULL as well.  Set i_blkno to 0 so that xfs_itobp() will
-        * know that this is a new incore inode.
-        */
-       error = xfs_itobp(mp, tp, ip, &dip, &bp, bno);
-
-       if (error != 0) {
-               kmem_zone_free(xfs_inode_zone, ip);
-               return error;
-       }
-
-       /*
-        * Initialize inode's trace buffers.
-        * Do this before xfs_iformat in case it adds entries.
-        */
-#ifdef XFS_BMAP_TRACE
-       ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
-#endif
-#ifdef XFS_BMBT_TRACE
-       ip->i_btrace = ktrace_alloc(XFS_BMBT_KTRACE_SIZE, KM_SLEEP);
-#endif
-#ifdef XFS_RW_TRACE
-       ip->i_rwtrace = ktrace_alloc(XFS_RW_KTRACE_SIZE, KM_SLEEP);
-#endif
-#ifdef XFS_ILOCK_TRACE
-       ip->i_lock_trace = ktrace_alloc(XFS_ILOCK_KTRACE_SIZE, KM_SLEEP);
-#endif
-#ifdef XFS_DIR2_TRACE
-       ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_SLEEP);
-#endif
-
-       /*
-        * If we got something that isn't an inode it means someone
-        * (nfs or dmi) has a stale handle.
-        */
-       if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
-               kmem_zone_free(xfs_inode_zone, ip);
-               xfs_trans_brelse(tp, bp);
-#ifdef DEBUG
-               xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-                               "dip->di_core.di_magic (0x%x) != "
-                               "XFS_DINODE_MAGIC (0x%x)",
-                               INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
-                               XFS_DINODE_MAGIC);
-#endif /* DEBUG */
-               return XFS_ERROR(EINVAL);
-       }
-
-       /*
-        * If the on-disk inode is already linked to a directory
-        * entry, copy all of the inode into the in-core inode.
-        * xfs_iformat() handles copying in the inode format
-        * specific information.
-        * Otherwise, just get the truly permanent information.
-        */
-       if (dip->di_core.di_mode) {
-               xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
-                    &(ip->i_d), 1);
-               error = xfs_iformat(ip, dip);
-               if (error)  {
-                       kmem_zone_free(xfs_inode_zone, ip);
-                       xfs_trans_brelse(tp, bp);
-#ifdef DEBUG
-                       xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-                                       "xfs_iformat() returned error %d",
-                                       error);
-#endif /* DEBUG */
-                       return error;
-               }
-       } else {
-               ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
-               ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
-               ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
-               ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
-               /*
-                * Make sure to pull in the mode here as well in
-                * case the inode is released without being used.
-                * This ensures that xfs_inactive() will see that
-                * the inode is already free and not try to mess
-                * with the uninitialized part of it.
-                */
-               ip->i_d.di_mode = 0;
-               /*
-                * Initialize the per-fork minima and maxima for a new
-                * inode here.  xfs_iformat will do it for old inodes.
-                */
-               ip->i_df.if_ext_max =
-                       XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
-       }
-
-       INIT_LIST_HEAD(&ip->i_reclaim);
-
-       /*
-        * The inode format changed when we moved the link count and
-        * made it 32 bits long.  If this is an old format inode,
-        * convert it in memory to look like a new one.  If it gets
-        * flushed to disk we will convert back before flushing or
-        * logging it.  We zero out the new projid field and the old link
-        * count field.  We'll handle clearing the pad field (the remains
-        * of the old uuid field) when we actually convert the inode to
-        * the new format. We don't change the version number so that we
-        * can distinguish this from a real new format inode.
-        */
-       if (ip->i_d.di_version == XFS_DINODE_VERSION_1) {
-               ip->i_d.di_nlink = ip->i_d.di_onlink;
-               ip->i_d.di_onlink = 0;
-               ip->i_d.di_projid = 0;
-       }
-
-       ip->i_delayed_blks = 0;
-
-       /*
-        * Mark the buffer containing the inode as something to keep
-        * around for a while.  This helps to keep recently accessed
-        * meta-data in-core longer.
-        */
-        XFS_BUF_SET_REF(bp, XFS_INO_REF);
-
-       /*
-        * Use xfs_trans_brelse() to release the buffer containing the
-        * on-disk inode, because it was acquired with xfs_trans_read_buf()
-        * in xfs_itobp() above.  If tp is NULL, this is just a normal
-        * brelse().  If we're within a transaction, then xfs_trans_brelse()
-        * will only release the buffer if it is not dirty within the
-        * transaction.  It will be OK to release the buffer in this case,
-        * because inodes on disk are never destroyed and we will be
-        * locking the new in-core inode before putting it in the hash
-        * table where other processes can find it.  Thus we don't have
-        * to worry about the inode being changed just because we released
-        * the buffer.
-        */
-       xfs_trans_brelse(tp, bp);
-       *ipp = ip;
-       return 0;
-}
-
 /*
  * Read in extents from a btree-format inode.
  * Allocate and fill in if_extents.  Real work is done in xfs_bmap.c.
index 6cd170abdb28e7896d99b21707fc9a7ac7f907e2..583293158fdf9fb5ffd091b9e694d1d2f5c08597 100644 (file)
@@ -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
@@ -212,6 +212,46 @@ xfs_xlatesb(
        }
 }
 
+/*
+ * xfs_mod_sb() can be used to copy arbitrary changes to the
+ * in-core superblock into the superblock buffer to be logged.
+ * It does not provide the higher level of locking that is
+ * needed to protect the in-core superblock from concurrent
+ * access.
+ */
+void
+xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
+{
+       xfs_buf_t       *bp;
+       int             first;
+       int             last;
+       xfs_mount_t     *mp;
+       xfs_sb_t        *sbp;
+       xfs_sb_field_t  f;
+
+       ASSERT(fields);
+       if (!fields)
+               return;
+       mp = tp->t_mountp;
+       bp = xfs_trans_getsb(tp, mp, 0);
+       sbp = XFS_BUF_TO_SBP(bp);
+       first = sizeof(xfs_sb_t);
+       last = 0;
+
+       /* translate/copy */
+       xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
+
+       /* find modified range */
+       f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
+       ASSERT((1LL << f) & XFS_SB_MOD_BITS);
+       first = xfs_sb_info[f].offset;
+       f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
+       ASSERT((1LL << f) & XFS_SB_MOD_BITS);
+       last = xfs_sb_info[f + 1].offset - 1;
+
+       xfs_trans_log_buf(tp, bp, first, last);
+}
+
 xfs_agnumber_t
 xfs_initialize_perag(xfs_mount_t *mp, xfs_agnumber_t agcount)
 {
index 6b4594e030e62cdc304d46237256a31e529780c1..03da415e3cfaf129f2ec6b1f435d282451665a60 100644 (file)
@@ -2030,6 +2030,7 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
        buf = libxfs_getbuf(xi.ddev, 0, BTOBB(WHACK_SIZE));
        bzero(XFS_BUF_PTR(buf), WHACK_SIZE);
        libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE);
+       libxfs_purgebuf(buf);
 
        /* OK, now write the superblock */
        buf = libxfs_getbuf(xi.ddev, XFS_SB_DADDR, XFS_FSS_TO_BB(mp, 1));
@@ -2331,6 +2332,14 @@ an AG size that is one stripe unit smaller, for example %llu.\n"),
                }
        }
 
+       /*
+        * Dump all inodes and buffers before marking us all done.
+        * Need to drop references to inodes we still hold, first.
+        */
+       libxfs_rtmount_destroy(mp);
+       libxfs_icache_purge();
+       libxfs_bcache_purge();
+
        /*
         * Mark the filesystem ok.
         */
index b3a421e9313278a2787bb02d95c7b7e23bf9d70a..d92f9599c97e0dc935c5c451350b7fb427d107f1 100644 (file)
@@ -719,8 +719,6 @@ mk_orphanage(xfs_mount_t *mp)
        int             error;
        xfs_bmap_free_t flist;
        const int       mode = 0755;
-       const int       uid = 0;
-       const int       gid = 0;
        int             nres;
 
        tp = libxfs_trans_alloc(mp, 0);
@@ -741,14 +739,10 @@ mk_orphanage(xfs_mount_t *mp)
 
        error = libxfs_inode_alloc(&tp, pip, mode|S_IFDIR,
                                        1, 0, &zerocr, &zerofsx, &ip);
-
        if (error) {
                do_error(_("%s inode allocation failed %d\n"),
                        ORPHANAGE, error);
        }
-
-       ip->i_d.di_uid = uid;
-       ip->i_d.di_gid = gid;
        ip->i_d.di_nlink++;             /* account for . */
 
        /*
index ee0eac553a40f2b63d75cbee76cea8d274855adc..80bbfc2a6fa3d1c6fb8b96ca2a7f7acd9d00ec3e 100644 (file)
@@ -42,6 +42,7 @@ static xfs_agino_t    agifreecount;
 void
 set_mp(xfs_mount_t *mpp)
 {
+       libxfs_bcache_purge();
        mp = mpp;
 }
 
@@ -1171,7 +1172,7 @@ scan_ag(
        agicount = agifreecount = 0;
 
        sbbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_SB_DADDR),
-                               1, 0);
+                               XFS_FSS_TO_BB(mp, 1), 0);
        if (!sbbuf)  {
                do_error(_("can't get root superblock for ag %d\n"), agno);
                return;
index 8693b47d67224bd2e58c36fd7771395bd91fae97..0acb2a0d36b51ae0888752b6f4da3fdbcd1d75ac 100644 (file)
@@ -500,6 +500,10 @@ main(int argc, char **argv)
 
        phase4(mp);
 
+       /* XXX: nathans - something in phase4 ain't playing by */
+       /* the buffer cache rules.. why doesn't IRIX hit this? */
+       libxfs_bcache_purge();
+
        if (no_modify)
                printf(_("No modify flag set, skipping phase 5\n"));
        else
@@ -577,6 +581,12 @@ _("Warning:  project quota information would be cleared.\n"
                return(0);
        }
 
+       /*
+        * Done, flush all cached buffers and inodes.
+        */
+       libxfs_icache_purge();
+       libxfs_bcache_purge();
+
        /*
         * Clear the quota flags if they're on.
         */