Merge of master-melb:xfs-cmds:25967a by kenmcd.
#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>
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);
#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 *);
* 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)
#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
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 **);
/*
* 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 */
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;
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);
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, \
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.
*/
}
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])
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;
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);
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");
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"),
}
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);
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);
* 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"),
}
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++) {
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);
+}
/*
- * 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)
{
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));
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;
}
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)
}
#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
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;
}
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);
}
+/*
+ * 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) {
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;
}
}
-/*
- * 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,
+};
/*
- * 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
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);
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);
}
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;
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,
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;
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
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);
return;
}
else {
- /*libxfs_iput(iip->ili_inode, 0); - nathans TODO? */
- libxfs_putbuf(bp);
+ libxfs_iput(iip->ili_inode, 0);
}
ili_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
}
}
+/*
+ * 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.
#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)
/* 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);
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.
/*
- * 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
}
}
+/*
+ * 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)
{
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));
}
}
+ /*
+ * 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.
*/
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);
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 . */
/*
void
set_mp(xfs_mount_t *mpp)
{
+ libxfs_bcache_purge();
mp = mpp;
}
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;
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
return(0);
}
+ /*
+ * Done, flush all cached buffers and inodes.
+ */
+ libxfs_icache_purge();
+ libxfs_bcache_purge();
+
/*
* Clear the quota flags if they're on.
*/